xref: /freebsd/contrib/openbsm/bin/auditd/auditd.c (revision 94942af266ac119ede0ca836f9aa5a5ac0582938)
1 /*
2  * Copyright (c) 2004 Apple Computer, Inc.
3  * All rights reserved.
4  *
5  * @APPLE_BSD_LICENSE_HEADER_START@
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
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  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
17  *     its contributors may be used to endorse or promote products derived
18  *     from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
21  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
24  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * @APPLE_BSD_LICENSE_HEADER_END@
32  *
33  * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.c#25 $
34  */
35 
36 #include <sys/types.h>
37 #include <sys/dirent.h>
38 #include <sys/mman.h>
39 #include <sys/queue.h>
40 #include <sys/stat.h>
41 #include <sys/wait.h>
42 
43 #include <bsm/audit.h>
44 #include <bsm/audit_uevents.h>
45 #include <bsm/libbsm.h>
46 
47 #include <err.h>
48 #include <errno.h>
49 #include <fcntl.h>
50 #include <grp.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <time.h>
54 #include <unistd.h>
55 #include <signal.h>
56 #include <string.h>
57 #include <syslog.h>
58 
59 #include "auditd.h"
60 
61 #define	NA_EVENT_STR_SIZE	25
62 #define	POL_STR_SIZE		128
63 
64 static int	 ret, minval;
65 static char	*lastfile = NULL;
66 static int	 allhardcount = 0;
67 static int	 triggerfd = 0;
68 static int	 sigchlds, sigchlds_handled;
69 static int	 sighups, sighups_handled;
70 static int	 sigterms, sigterms_handled;
71 
72 static TAILQ_HEAD(, dir_ent)	dir_q;
73 
74 static int	config_audit_controls(void);
75 
76 /*
77  * Error starting auditd
78  */
79 static void
80 fail_exit(void)
81 {
82 
83 	audit_warn_nostart();
84 	exit(1);
85 }
86 
87 /*
88  * Free our local list of directory names.
89  */
90 static void
91 free_dir_q(void)
92 {
93 	struct dir_ent *dirent;
94 
95 	while ((dirent = TAILQ_FIRST(&dir_q))) {
96 		TAILQ_REMOVE(&dir_q, dirent, dirs);
97 		free(dirent->dirname);
98 		free(dirent);
99 	}
100 }
101 
102 /*
103  * Generate the timestamp string.
104  */
105 static int
106 getTSstr(char *buf, int len)
107 {
108 	struct timeval ts;
109 	struct timezone tzp;
110 	time_t tt;
111 
112 	if (gettimeofday(&ts, &tzp) != 0)
113 		return (-1);
114 	tt = (time_t)ts.tv_sec;
115 	if (!strftime(buf, len, "%Y%m%d%H%M%S", gmtime(&tt)))
116 		return (-1);
117 	return (0);
118 }
119 
120 /*
121  * Concat the directory name to the given file name.
122  * XXX We should affix the hostname also
123  */
124 static char *
125 affixdir(char *name, struct dir_ent *dirent)
126 {
127 	char *fn;
128 	char *curdir;
129 	const char *sep = "/";
130 
131 	curdir = dirent->dirname;
132 	syslog(LOG_DEBUG, "dir = %s", dirent->dirname);
133 
134 	fn = malloc(strlen(curdir) + strlen(sep) + (2 * POSTFIX_LEN) + 1);
135 	if (fn == NULL)
136 		return (NULL);
137 	strcpy(fn, curdir);
138 	strcat(fn, sep);
139 	strcat(fn, name);
140 	return (fn);
141 }
142 
143 /*
144  * Close the previous audit trail file.
145  */
146 static int
147 close_lastfile(char *TS)
148 {
149 	char *ptr;
150 	char *oldname;
151 
152 	if (lastfile != NULL) {
153 		oldname = (char *)malloc(strlen(lastfile) + 1);
154 		if (oldname == NULL)
155 			return (-1);
156 		strcpy(oldname, lastfile);
157 
158 		/* Rename the last file -- append timestamp. */
159 		if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) {
160 			*ptr = '.';
161 			strcpy(ptr+1, TS);
162 			if (rename(oldname, lastfile) != 0)
163 				syslog(LOG_ERR,
164 				    "Could not rename %s to %s: %m", oldname,
165 				    lastfile);
166 			else {
167 				syslog(LOG_INFO, "renamed %s to %s",
168 				    oldname, lastfile);
169 				audit_warn_closefile(lastfile);
170 			}
171 		}
172 		free(lastfile);
173 		free(oldname);
174 		lastfile = NULL;
175 	}
176 	return (0);
177 }
178 
179 /*
180  * Create the new audit file with appropriate permissions and ownership.  Try
181  * to clean up if something goes wrong.
182  */
183 static int
184 #ifdef AUDIT_REVIEW_GROUP
185 open_trail(const char *fname, uid_t uid, gid_t gid)
186 #else
187 open_trail(const char *fname)
188 #endif
189 {
190 	int error, fd;
191 
192 	fd = open(fname, O_RDONLY | O_CREAT, S_IRUSR | S_IRGRP);
193 	if (fd < 0)
194 		return (-1);
195 #ifdef AUDIT_REVIEW_GROUP
196 	if (fchown(fd, uid, gid) < 0) {
197 		error = errno;
198 		close(fd);
199 		(void)unlink(fname);
200 		errno = error;
201 		return (-1);
202 	}
203 #endif
204 	return (fd);
205 }
206 
207 /*
208  * Create the new file name, swap with existing audit file.
209  */
210 static int
211 swap_audit_file(void)
212 {
213 	char timestr[2 * POSTFIX_LEN];
214 	char *fn;
215 	char TS[POSTFIX_LEN];
216 	struct dir_ent *dirent;
217 #ifdef AUDIT_REVIEW_GROUP
218 	struct group *grp;
219 	gid_t gid;
220 	uid_t uid;
221 #endif
222 	int error, fd;
223 
224 	if (getTSstr(TS, POSTFIX_LEN) != 0)
225 		return (-1);
226 
227 	strcpy(timestr, TS);
228 	strcat(timestr, NOT_TERMINATED);
229 
230 #ifdef AUDIT_REVIEW_GROUP
231 	/*
232 	 * XXXRW: Currently, this code falls back to the daemon gid, which is
233 	 * likely the wheel group.  Is there a better way to deal with this?
234 	 */
235 	grp = getgrnam(AUDIT_REVIEW_GROUP);
236 	if (grp == NULL) {
237 		syslog(LOG_INFO,
238 		    "Audit review group '%s' not available, using daemon gid",
239 		    AUDIT_REVIEW_GROUP);
240 		gid = -1;
241 	} else
242 		gid = grp->gr_gid;
243 	uid = getuid();
244 #endif
245 
246 	/* Try until we succeed. */
247 	while ((dirent = TAILQ_FIRST(&dir_q))) {
248 		if ((fn = affixdir(timestr, dirent)) == NULL) {
249 			syslog(LOG_INFO, "Failed to swap log at time %s",
250 				timestr);
251 			return (-1);
252 		}
253 
254 		/*
255 		 * Create and open the file; then close and pass to the
256 		 * kernel if all went well.
257 		 */
258 		syslog(LOG_INFO, "New audit file is %s", fn);
259 #ifdef AUDIT_REVIEW_GROUP
260 		fd = open_trail(fn, uid, gid);
261 #else
262 		fd = open_trail(fn);
263 #endif
264 		if (fd < 0)
265 			warn("open(%s)", fn);
266 		if (fd >= 0) {
267 			error = auditctl(fn);
268 			if (error) {
269 				syslog(LOG_ERR,
270 				    "auditctl failed setting log file! : %s",
271 				    strerror(errno));
272 				close(fd);
273 			} else {
274 				/* Success. */
275 				close_lastfile(TS);
276 				lastfile = fn;
277 				close(fd);
278 				return (0);
279 			}
280 		}
281 
282 		/*
283 		 * Tell the administrator about lack of permissions for dir.
284 		 */
285 		audit_warn_getacdir(dirent->dirname);
286 
287 		/* Try again with a different directory. */
288 		TAILQ_REMOVE(&dir_q, dirent, dirs);
289 		free(dirent->dirname);
290 		free(dirent);
291 	}
292 	syslog(LOG_ERR, "Log directories exhausted");
293 	return (-1);
294 }
295 
296 /*
297  * Read the audit_control file contents.
298  */
299 static int
300 read_control_file(void)
301 {
302 	char cur_dir[MAXNAMLEN];
303 	struct dir_ent *dirent;
304 	au_qctrl_t qctrl;
305 
306 	/*
307 	 * Clear old values.  Force a re-read of the file the next time.
308 	 */
309 	free_dir_q();
310 	endac();
311 
312 	/*
313 	 * Read the list of directories into a local linked list.
314 	 *
315 	 * XXX We should use the reentrant interfaces once they are
316 	 * available.
317 	 */
318 	while (getacdir(cur_dir, MAXNAMLEN) >= 0) {
319 		dirent = (struct dir_ent *) malloc(sizeof(struct dir_ent));
320 		if (dirent == NULL)
321 			return (-1);
322 		dirent->softlim = 0;
323 		dirent->dirname = (char *) malloc(MAXNAMLEN);
324 		if (dirent->dirname == NULL) {
325 			free(dirent);
326 			return (-1);
327 		}
328 		strcpy(dirent->dirname, cur_dir);
329 		TAILQ_INSERT_TAIL(&dir_q, dirent, dirs);
330 	}
331 
332 	allhardcount = 0;
333 	if (swap_audit_file() == -1) {
334 		syslog(LOG_ERR, "Could not swap audit file");
335 		/*
336 		 * XXX Faulty directory listing? - user should be given
337 		 * XXX an opportunity to change the audit_control file
338 		 * XXX switch to a reduced mode of auditing?
339 		 */
340 		return (-1);
341 	}
342 
343 	/*
344 	 * XXX There are synchronization problems here
345  	 * XXX what should we do if a trigger for the earlier limit
346 	 * XXX is generated here?
347 	 */
348 	if (0 == (ret = getacmin(&minval))) {
349 		syslog(LOG_DEBUG, "min free = %d", minval);
350 		if (auditon(A_GETQCTRL, &qctrl, sizeof(qctrl)) != 0) {
351 			syslog(LOG_ERR,
352 			    "could not get audit queue settings");
353 				return (-1);
354 		}
355 		qctrl.aq_minfree = minval;
356 		if (auditon(A_SETQCTRL, &qctrl, sizeof(qctrl)) != 0) {
357 			syslog(LOG_ERR,
358 			    "could not set audit queue settings");
359 			return (-1);
360 		}
361 	}
362 
363 	return (0);
364 }
365 
366 /*
367  * Close all log files, control files, and tell the audit system.
368  */
369 static int
370 close_all(void)
371 {
372 	struct auditinfo ai;
373 	int err_ret = 0;
374 	char TS[POSTFIX_LEN];
375 	int aufd;
376 	token_t *tok;
377 	long cond;
378 
379 	/* Generate an audit record. */
380 	if ((aufd = au_open()) == -1)
381 		syslog(LOG_ERR, "Could not create audit shutdown event.");
382 	else {
383 		if ((tok = au_to_text("auditd::Audit shutdown")) != NULL)
384 			au_write(aufd, tok);
385 		/*
386 		 * XXX we need to implement extended subject tokens so we can
387 		 * effectively represent terminal lines with this token type.
388 		 */
389 		bzero(&ai, sizeof(ai));
390 		if ((tok = au_to_subject32(getuid(), geteuid(), getegid(),
391 		    getuid(), getgid(), getpid(), getpid(), &ai.ai_termid))
392 		    != NULL)
393 			au_write(aufd, tok);
394 		if ((tok = au_to_return32(0, 0)) != NULL)
395 			au_write(aufd, tok);
396 		if (au_close(aufd, 1, AUE_audit_shutdown) == -1)
397 			syslog(LOG_ERR,
398 			    "Could not close audit shutdown event.");
399 	}
400 
401 	/* Flush contents. */
402 	cond = AUC_DISABLED;
403 	err_ret = auditon(A_SETCOND, &cond, sizeof(cond));
404 	if (err_ret != 0) {
405 		syslog(LOG_ERR, "Disabling audit failed! : %s",
406 		    strerror(errno));
407 		err_ret = 1;
408 	}
409 	if (getTSstr(TS, POSTFIX_LEN) == 0)
410 		close_lastfile(TS);
411 	if (lastfile != NULL)
412 		free(lastfile);
413 
414 	free_dir_q();
415 	if ((remove(AUDITD_PIDFILE) == -1) || err_ret) {
416 		syslog(LOG_ERR, "Could not unregister");
417 		audit_warn_postsigterm();
418 		return (1);
419 	}
420 	endac();
421 
422 	if (close(triggerfd) != 0)
423 		syslog(LOG_ERR, "Error closing control file");
424 	syslog(LOG_INFO, "Finished");
425 	return (0);
426 }
427 
428 /*
429  * When we get a signal, we are often not at a clean point.  So, little can
430  * be done in the signal handler itself.  Instead,  we send a message to the
431  * main servicing loop to do proper handling from a non-signal-handler
432  * context.
433  */
434 static void
435 relay_signal(int signal)
436 {
437 
438 	if (signal == SIGHUP)
439 		sighups++;
440 	if (signal == SIGTERM)
441 		sigterms++;
442 	if (signal == SIGCHLD)
443 		sigchlds++;
444 }
445 
446 /*
447  * Registering the daemon.
448  */
449 static int
450 register_daemon(void)
451 {
452 	FILE * pidfile;
453 	int fd;
454 	pid_t pid;
455 
456 	/* Set up the signal hander. */
457 	if (signal(SIGTERM, relay_signal) == SIG_ERR) {
458 		syslog(LOG_ERR,
459 		    "Could not set signal handler for SIGTERM");
460 		fail_exit();
461 	}
462 	if (signal(SIGCHLD, relay_signal) == SIG_ERR) {
463 		syslog(LOG_ERR,
464 		    "Could not set signal handler for SIGCHLD");
465 		fail_exit();
466 	}
467 	if (signal(SIGHUP, relay_signal) == SIG_ERR) {
468 		syslog(LOG_ERR,
469 		    "Could not set signal handler for SIGHUP");
470 		fail_exit();
471 	}
472 
473 	if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) {
474 		syslog(LOG_ERR, "Could not open PID file");
475 		audit_warn_tmpfile();
476 		return (-1);
477 	}
478 
479 	/* Attempt to lock the pid file; if a lock is present, exit. */
480 	fd = fileno(pidfile);
481 	if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
482 		syslog(LOG_ERR,
483 		    "PID file is locked (is another auditd running?).");
484 		audit_warn_ebusy();
485 		return (-1);
486 	}
487 
488 	pid = getpid();
489 	ftruncate(fd, 0);
490 	if (fprintf(pidfile, "%u\n", pid) < 0) {
491 		/* Should not start the daemon. */
492 		fail_exit();
493 	}
494 
495 	fflush(pidfile);
496 	return (0);
497 }
498 
499 /*
500  * Handle the audit trigger event.
501  *
502  * We suppress (ignore) duplicated triggers in close succession in order to
503  * try to avoid thrashing-like behavior.  However, not all triggers can be
504  * ignored, as triggers generally represent edge triggers, not level
505  * triggers, and won't be retransmitted if the condition persists.  Of
506  * specific concern is the rotate trigger -- if one is dropped, then it will
507  * not be retransmitted, and the log file will grow in an unbounded fashion.
508  */
509 #define	DUPLICATE_INTERVAL	30
510 static void
511 handle_audit_trigger(int trigger)
512 {
513 	static int last_trigger, last_warning;
514 	static time_t last_time;
515 	struct dir_ent *dirent;
516 	struct timeval ts;
517 	struct timezone tzp;
518 	time_t tt;
519 
520 	/*
521 	 * Suppress duplicate messages from the kernel within the specified
522 	 * interval.
523 	 */
524 	if (gettimeofday(&ts, &tzp) == 0) {
525 		tt = (time_t)ts.tv_sec;
526 		switch (trigger) {
527 		case AUDIT_TRIGGER_LOW_SPACE:
528 		case AUDIT_TRIGGER_NO_SPACE:
529 			/*
530 			 * Triggers we can suppress.  Of course, we also need
531 			 * to rate limit the warnings, so apply the same
532 			 * interval limit on syslog messages.
533 			 */
534 			if ((trigger == last_trigger) &&
535 			    (tt < (last_time + DUPLICATE_INTERVAL))) {
536 				if (tt >= (last_warning + DUPLICATE_INTERVAL))
537 					syslog(LOG_INFO,
538 					    "Suppressing duplicate trigger %d",
539 					    trigger);
540 				return;
541 			}
542 			last_warning = tt;
543 			break;
544 
545 		case AUDIT_TRIGGER_ROTATE_KERNEL:
546 		case AUDIT_TRIGGER_ROTATE_USER:
547 		case AUDIT_TRIGGER_READ_FILE:
548 			/*
549 			 * Triggers that we cannot suppress.
550 			 */
551 			break;
552 		}
553 
554 		/*
555 		 * Only update last_trigger after aborting due to a duplicate
556 		 * trigger, not before, or we will never allow that trigger
557 		 * again.
558 		 */
559 		last_trigger = trigger;
560 		last_time = tt;
561 	}
562 
563 	/*
564 	 * Message processing is done here.
565  	 */
566 	dirent = TAILQ_FIRST(&dir_q);
567 	switch(trigger) {
568 	case AUDIT_TRIGGER_LOW_SPACE:
569 		syslog(LOG_INFO, "Got low space trigger");
570 		if (dirent && (dirent->softlim != 1)) {
571 			TAILQ_REMOVE(&dir_q, dirent, dirs);
572 				/* Add this node to the end of the list. */
573 				TAILQ_INSERT_TAIL(&dir_q, dirent, dirs);
574 				audit_warn_soft(dirent->dirname);
575 				dirent->softlim = 1;
576 
577 			if (TAILQ_NEXT(TAILQ_FIRST(&dir_q), dirs) != NULL &&
578 			    swap_audit_file() == -1)
579 				syslog(LOG_ERR, "Error swapping audit file");
580 
581 			/*
582 			 * Check if the next dir has already reached its soft
583 			 * limit.
584 			 */
585 			dirent = TAILQ_FIRST(&dir_q);
586 			if (dirent->softlim == 1)  {
587 				/* All dirs have reached their soft limit. */
588 				audit_warn_allsoft();
589 			}
590 		} else {
591 			/*
592 			 * Continue auditing to the current file.  Also
593 			 * generate an allsoft warning.
594 			 *
595 			 * XXX do we want to do this ?
596 			 */
597 			audit_warn_allsoft();
598 		}
599 		break;
600 
601 	case AUDIT_TRIGGER_NO_SPACE:
602 		syslog(LOG_INFO, "Got no space trigger");
603 
604 		/* Delete current dir, go on to next. */
605 		TAILQ_REMOVE(&dir_q, dirent, dirs);
606 		audit_warn_hard(dirent->dirname);
607 		free(dirent->dirname);
608 		free(dirent);
609 
610 		if (swap_audit_file() == -1)
611 			syslog(LOG_ERR, "Error swapping audit file");
612 
613 		/* We are out of log directories. */
614 		audit_warn_allhard(++allhardcount);
615 		break;
616 
617 	case AUDIT_TRIGGER_ROTATE_KERNEL:
618 	case AUDIT_TRIGGER_ROTATE_USER:
619 		/*
620 		 * Create a new file and swap with the one being used in
621 		 * kernel
622 		 */
623 		syslog(LOG_INFO, "Got open new trigger from %s", trigger ==
624 		    AUDIT_TRIGGER_ROTATE_KERNEL ? "kernel" : "user");
625 		if (swap_audit_file() == -1)
626 			syslog(LOG_ERR, "Error swapping audit file");
627 		break;
628 
629 	case AUDIT_TRIGGER_READ_FILE:
630 		syslog(LOG_INFO, "Got read file trigger");
631 		if (read_control_file() == -1)
632 			syslog(LOG_ERR, "Error in audit control file");
633 		if (config_audit_controls() == -1)
634 			syslog(LOG_ERR, "Error setting audit controls");
635 		break;
636 
637 	default:
638 		syslog(LOG_ERR, "Got unknown trigger %d", trigger);
639 		break;
640 	}
641 }
642 
643 static void
644 handle_sighup(void)
645 {
646 
647 	sighups_handled = sighups;
648 	config_audit_controls();
649 }
650 
651 /*
652  * Reap our children.
653  */
654 static void
655 reap_children(void)
656 {
657 	pid_t child;
658 	int wstatus;
659 
660 	while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) {
661 		if (!wstatus)
662 			continue;
663 		syslog(LOG_INFO, "warn process [pid=%d] %s %d.", child,
664 		    ((WIFEXITED(wstatus)) ? "exited with non-zero status" :
665 		    "exited as a result of signal"),
666 		    ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) :
667 		    WTERMSIG(wstatus)));
668 	}
669 }
670 
671 static void
672 handle_sigchld(void)
673 {
674 
675 	sigchlds_handled = sigchlds;
676 	reap_children();
677 }
678 
679 /*
680  * Read the control file for triggers/signals and handle appropriately.
681  */
682 static int
683 wait_for_events(void)
684 {
685 	int num;
686 	unsigned int trigger;
687 
688 	for (;;) {
689 		num = read(triggerfd, &trigger, sizeof(trigger));
690 		if ((num == -1) && (errno != EINTR)) {
691 			syslog(LOG_ERR, "%s: error %d", __FUNCTION__, errno);
692 			return (-1);
693 		}
694 		if (sigterms != sigterms_handled) {
695 			syslog(LOG_DEBUG, "%s: SIGTERM", __FUNCTION__);
696 			break;
697 		}
698 		if (sigchlds != sigchlds_handled)
699 			handle_sigchld();
700 		if (sighups != sighups_handled) {
701 			syslog(LOG_DEBUG, "%s: SIGHUP", __FUNCTION__);
702 			handle_sighup();
703 		}
704 		if ((num == -1) && (errno == EINTR))
705 			continue;
706 		if (num == 0) {
707 			syslog(LOG_ERR, "%s: read EOF", __FUNCTION__);
708 			return (-1);
709 		}
710 		if (trigger == AUDIT_TRIGGER_CLOSE_AND_DIE)
711 			break;
712 		else
713 			handle_audit_trigger(trigger);
714 	}
715 	return (close_all());
716 }
717 
718 /*
719  * Configure the audit controls in the kernel: the event to class mapping,
720  * kernel preselection mask, etc.
721  */
722 static int
723 config_audit_controls(void)
724 {
725 	au_event_ent_t ev, *evp;
726 	au_evclass_map_t evc_map;
727 	au_mask_t aumask;
728 	int ctr = 0;
729 	char naeventstr[NA_EVENT_STR_SIZE];
730 	char polstr[POL_STR_SIZE];
731 	long policy;
732 	au_fstat_t au_fstat;
733 	size_t filesz;
734 
735 	/*
736 	 * Process the audit event file, obtaining a class mapping for each
737 	 * event, and send that mapping into the kernel.
738 	 *
739 	 * XXX There's a risk here that the BSM library will return NULL
740 	 * for an event when it can't properly map it to a class. In that
741 	 * case, we will not process any events beyond the one that failed,
742 	 * but should. We need a way to get a count of the events.
743 	*/
744 	ev.ae_name = (char *)malloc(AU_EVENT_NAME_MAX);
745 	ev.ae_desc = (char *)malloc(AU_EVENT_DESC_MAX);
746 	if ((ev.ae_name == NULL) || (ev.ae_desc == NULL)) {
747 		if (ev.ae_name != NULL)
748 			free(ev.ae_name);
749 		syslog(LOG_ERR,
750 		    "Memory allocation error when configuring audit controls.");
751 		return (-1);
752 	}
753 
754 	/*
755 	 * XXXRW: Currently we have no way to remove mappings from the kernel
756 	 * when they are removed from the file-based mappings.
757 	 */
758 	evp = &ev;
759 	setauevent();
760 	while ((evp = getauevent_r(evp)) != NULL) {
761 		evc_map.ec_number = evp->ae_number;
762 		evc_map.ec_class = evp->ae_class;
763 		if (auditon(A_SETCLASS, &evc_map, sizeof(au_evclass_map_t))
764 		    != 0)
765 			syslog(LOG_ERR,
766 				"Failed to register class mapping for event %s",
767 				 evp->ae_name);
768 		else
769 			ctr++;
770 	}
771 	endauevent();
772 	free(ev.ae_name);
773 	free(ev.ae_desc);
774 	if (ctr == 0)
775 		syslog(LOG_ERR, "No events to class mappings registered.");
776 	else
777 		syslog(LOG_DEBUG, "Registered %d event to class mappings.",
778 		    ctr);
779 
780 	/*
781 	 * Get the non-attributable event string and set the kernel mask from
782 	 * that.
783 	 */
784 	if ((getacna(naeventstr, NA_EVENT_STR_SIZE) == 0) &&
785 	    (getauditflagsbin(naeventstr, &aumask) == 0)) {
786 		if (auditon(A_SETKMASK, &aumask, sizeof(au_mask_t)))
787 			syslog(LOG_ERR,
788 			    "Failed to register non-attributable event mask.");
789 		else
790 			syslog(LOG_DEBUG,
791 			    "Registered non-attributable event mask.");
792 	} else
793 		syslog(LOG_ERR,
794 		    "Failed to obtain non-attributable event mask.");
795 
796 	/*
797 	 * If a policy is configured in audit_control(5), implement the
798 	 * policy.  However, if one isn't defined, set AUDIT_CNT to avoid
799 	 * leaving the system in a fragile state.
800 	 */
801 	if ((getacpol(polstr, POL_STR_SIZE) == 0) &&
802 	    (au_strtopol(polstr, &policy) == 0)) {
803 		if (auditon(A_SETPOLICY, &policy, sizeof(policy)))
804 			syslog(LOG_ERR, "Failed to set audit policy: %m");
805 	} else {
806 		syslog(LOG_ERR, "Failed to obtain policy flags: %m");
807 		policy = AUDIT_CNT;
808 		if (auditon(A_SETPOLICY, &policy, sizeof(policy)))
809 			syslog(LOG_ERR,
810 			    "Failed to set default audit policy: %m");
811 	}
812 
813 	/*
814 	 * Set trail rotation size.
815 	 */
816 	if (getacfilesz(&filesz) == 0) {
817 		bzero(&au_fstat, sizeof(au_fstat));
818 		au_fstat.af_filesz = filesz;
819 		if (auditon(A_SETFSIZE, &au_fstat, sizeof(au_fstat)) < 0)
820 			syslog(LOG_ERR, "Failed to set filesz: %m");
821 	} else
822 		syslog(LOG_ERR, "Failed to obtain filesz: %m");
823 
824 	return (0);
825 }
826 
827 static void
828 setup(void)
829 {
830 	struct auditinfo ai;
831 	auditinfo_t auinfo;
832 	int aufd;
833 	token_t *tok;
834 
835 	if ((triggerfd = open(AUDIT_TRIGGER_FILE, O_RDONLY, 0)) < 0) {
836 		syslog(LOG_ERR, "Error opening trigger file");
837 		fail_exit();
838 	}
839 
840 	/*
841 	 * To provide event feedback cycles and avoid auditd becoming
842 	 * stalled if auditing is suspended, auditd and its children run
843 	 * without their events being audited.  We allow the uid, tid, and
844 	 * mask fields to be implicitly set to zero, but do set the pid.  We
845 	 * run this after opening the trigger device to avoid configuring
846 	 * audit state without audit present in the system.
847 	 *
848 	 * XXXRW: Is there more to it than this?
849 	 */
850 	bzero(&auinfo, sizeof(auinfo));
851 	auinfo.ai_asid = getpid();
852 	if (setaudit(&auinfo) == -1) {
853 		syslog(LOG_ERR, "Error setting audit stat");
854 		fail_exit();
855 	}
856 
857 	TAILQ_INIT(&dir_q);
858 	if (read_control_file() == -1) {
859 		syslog(LOG_ERR, "Error reading control file");
860 		fail_exit();
861 	}
862 
863 	/* Generate an audit record. */
864 	if ((aufd = au_open()) == -1)
865 		syslog(LOG_ERR, "Could not create audit startup event.");
866 	else {
867 		/*
868 		 * XXXCSJP Perhaps we want more robust audit records for
869 		 * audit start up and shutdown. This might include capturing
870 		 * failures to initialize the audit subsystem?
871 		 */
872 		bzero(&ai, sizeof(ai));
873 		if ((tok = au_to_subject32(getuid(), geteuid(), getegid(),
874 		    getuid(), getgid(), getpid(), getpid(), &ai.ai_termid))
875 		    != NULL)
876 			au_write(aufd, tok);
877 		if ((tok = au_to_text("auditd::Audit startup")) != NULL)
878 			au_write(aufd, tok);
879 		if ((tok = au_to_return32(0, 0)) != NULL)
880 			au_write(aufd, tok);
881 		if (au_close(aufd, 1, AUE_audit_startup) == -1)
882 			syslog(LOG_ERR,
883 			    "Could not close audit startup event.");
884 	}
885 
886 	if (config_audit_controls() == 0)
887 		syslog(LOG_INFO, "Audit controls init successful");
888 	else
889 		syslog(LOG_ERR, "Audit controls init failed");
890 }
891 
892 int
893 main(int argc, char **argv)
894 {
895 	int ch;
896 	int debug = 0;
897 	int rc;
898 
899 	while ((ch = getopt(argc, argv, "d")) != -1) {
900 		switch(ch) {
901 		case 'd':
902 			/* Debug option. */
903 			debug = 1;
904 			break;
905 
906 		case '?':
907 		default:
908 			(void)fprintf(stderr,
909 			    "usage: auditd [-d] \n");
910 			exit(1);
911 		}
912 	}
913 
914 #ifdef LOG_SECURITY
915 	openlog("auditd", LOG_CONS | LOG_PID, LOG_SECURITY);
916 #else
917 	openlog("auditd", LOG_CONS | LOG_PID, LOG_AUTH);
918 #endif
919 	syslog(LOG_INFO, "starting...");
920 
921 	if (debug == 0 && daemon(0, 0) == -1) {
922 		syslog(LOG_ERR, "Failed to daemonize");
923 		exit(1);
924 	}
925 
926 	if (register_daemon() == -1) {
927 		syslog(LOG_ERR, "Could not register as daemon");
928 		exit(1);
929 	}
930 
931 	setup();
932 
933 	rc = wait_for_events();
934 	syslog(LOG_INFO, "auditd exiting.");
935 
936 	exit(rc);
937 }
938