]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/openbsm/bin/auditd/auditd.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / openbsm / bin / auditd / auditd.c
1 /*-
2  * Copyright (c) 2004-2009 Apple Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.c#50 $
30  */
31
32 #include <sys/types.h>
33
34 #include <config/config.h>
35
36 #include <sys/dirent.h>
37 #ifdef HAVE_FULL_QUEUE_H
38 #include <sys/queue.h>
39 #else   /* !HAVE_FULL_QUEUE_H */
40 #include <compat/queue.h>
41 #endif  /* !HAVE_FULL_QUEUE_H */
42 #include <sys/mman.h>
43 #include <sys/param.h>
44 #include <sys/stat.h>
45 #include <sys/wait.h>
46
47 #include <bsm/audit.h>
48 #include <bsm/audit_uevents.h>
49 #include <bsm/auditd_lib.h>
50 #include <bsm/libbsm.h>
51
52 #include <err.h>
53 #include <errno.h>
54 #include <fcntl.h>
55 #include <grp.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <time.h>
59 #include <unistd.h>
60 #include <signal.h>
61 #include <string.h>
62
63 #include "auditd.h"
64
65 #ifndef HAVE_STRLCPY
66 #include <compat/strlcpy.h>
67 #endif
68
69 /*
70  * XXX The following are temporary until these can be added to the kernel
71  * audit.h header.
72  */
73 #ifndef AUDIT_TRIGGER_INITIALIZE
74 #define AUDIT_TRIGGER_INITIALIZE        7
75 #endif
76 #ifndef AUDIT_TRIGGER_EXPIRE_TRAILS
77 #define AUDIT_TRIGGER_EXPIRE_TRAILS     8
78 #endif
79
80
81 /*
82  * LaunchD flag (Mac OS X and, maybe, FreeBSD only.)  See launchd(8) and
83  * http://wiki.freebsd.org/launchd for more information.
84  *
85  *      In order for auditd to work "on demand" with launchd(8) it can't:
86  *              call daemon(3)
87  *              call fork and having the parent process exit
88  *              change uids or gids.
89  *              set up the current working directory or chroot.
90  *              set the session id
91  *              change stdio to /dev/null.
92  *              call setrusage(2)
93  *              call setpriority(2)
94  *              Ignore SIGTERM.
95  *      auditd (in 'launchd mode') is launched on demand so it must catch
96  *      SIGTERM to exit cleanly.
97  */
98 static int      launchd_flag = 0;
99
100 /*
101  * The GID of the audit review group (if used).  The audit trail files and
102  * system logs (Mac OS X only) can only be reviewed by members of this group
103  * or the audit administrator (aka. "root").
104  */
105 static gid_t    audit_review_gid = -1;
106
107 /*
108  * The path and file name of the last audit trail file.
109  */
110 static char     *lastfile = NULL;
111
112 /*
113  * Error starting auditd. Run warn script and exit.
114  */
115 static void
116 fail_exit(void)
117 {
118
119         audit_warn_nostart();
120         exit(1);
121 }
122
123 /*
124  * Follow the 'current' symlink to get the active trail file name.
125  */
126 static char *
127 get_curfile(void)
128 {
129         char *cf;
130         int len;
131
132         cf = malloc(MAXPATHLEN);
133         if (cf == NULL) {
134                 auditd_log_err("malloc failed: %m");
135                 return (NULL);
136         }
137
138         len = readlink(AUDIT_CURRENT_LINK, cf, MAXPATHLEN - 1);
139         if (len < 0) {
140                 free(cf);
141                 return (NULL);
142         }
143
144         /* readlink() doesn't terminate string. */
145         cf[len] = '\0';
146
147         return (cf);
148 }
149
150 /*
151  * Close the previous audit trail file.
152  */
153 static int
154 close_lastfile(char *TS)
155 {
156         char *ptr;
157         char *oldname;
158
159         /* If lastfile is NULL try to get it from the 'current' link.  */
160         if (lastfile == NULL)
161                 lastfile = get_curfile();
162
163         if (lastfile != NULL) {
164                 oldname = strdup(lastfile);
165                 if (oldname == NULL)
166                         return (-1);
167
168                 /* Rename the last file -- append timestamp. */
169                 if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) {
170                         memcpy(ptr, TS, POSTFIX_LEN);
171                         if (auditd_rename(oldname, lastfile) != 0)
172                                 auditd_log_err(
173                                     "Could not rename %s to %s: %m", oldname,
174                                     lastfile);
175                         else {
176                                 /*
177                                  * Remove the 'current' symlink since the link
178                                  * is now invalid.
179                                  */
180                                 (void) unlink(AUDIT_CURRENT_LINK);
181                                 auditd_log_notice("renamed %s to %s",
182                                     oldname, lastfile);
183                                 audit_warn_closefile(lastfile);
184                         }
185                 } else
186                         auditd_log_err("Could not rename %s to %s", oldname,
187                             lastfile);
188                 free(lastfile);
189                 free(oldname);
190                 lastfile = NULL;
191         }
192         return (0);
193 }
194
195 /*
196  * Create the new file name, swap with existing audit file.
197  */
198 static int
199 swap_audit_file(void)
200 {
201         int err;
202         char *newfile, *name;
203         char TS[TIMESTAMP_LEN + 1];
204         time_t tt;
205
206         if (getTSstr(tt, TS, sizeof(TS)) != 0)
207                 return (-1);
208         /*
209          * If prefix and suffix are the same, it means that records are
210          * being produced too fast. We don't want to rename now, because
211          * next trail file can get the same name and once that one is
212          * terminated also within one second it will overwrite the current
213          * one. Just keep writing to the same trail and wait for the next
214          * trigger from the kernel.
215          * FREEBSD KERNEL WAS UPDATED TO KEEP SENDING TRIGGERS, WHICH MIGHT
216          * NOT BE THE CASE FOR OTHER OSES.
217          * If the kernel will not keep sending triggers, trail file will not
218          * be terminated.
219          */
220         if (lastfile == NULL) {
221                 name = NULL;
222         } else {
223                 name = strrchr(lastfile, '/');
224                 if (name != NULL)
225                         name++;
226         }
227         if (name != NULL && strncmp(name, TS, TIMESTAMP_LEN) == 0) {
228                 auditd_log_debug("Not ready to terminate trail file yet.");
229                 return (0);
230         }
231         err = auditd_swap_trail(TS, &newfile, audit_review_gid,
232             audit_warn_getacdir);
233         if (err != ADE_NOERR) {
234                 auditd_log_err("%s: %m", auditd_strerror(err));
235                 if (err != ADE_ACTL)
236                         return (-1);
237         }
238
239         /*
240          * Only close the last file if were in an auditing state before
241          * calling swap_audit_file().  We may need to recover from a crash.
242          */
243         if (auditd_get_state() == AUD_STATE_ENABLED)
244                 close_lastfile(TS);
245
246
247         /*
248          * auditd_swap_trail() potentially enables auditing (if not already
249          * enabled) so updated the cached state as well.
250          */
251         auditd_set_state(AUD_STATE_ENABLED);
252
253         /*
254          *  Create 'current' symlink.  Recover from crash, if needed.
255          */
256         if (auditd_new_curlink(newfile) != 0)
257                 auditd_log_err("auditd_new_curlink(\"%s\") failed: %s: %m",
258                     newfile, auditd_strerror(err));
259
260         lastfile = newfile;
261         auditd_log_notice("New audit file is %s", newfile);
262
263         return (0);
264 }
265
266 /*
267  * Create a new audit log trail file and swap with the current one, if any.
268  */
269 static int
270 do_trail_file(void)
271 {
272         int err;
273
274         /*
275          * First, refresh the list of audit log directories.
276          */
277         err = auditd_read_dirs(audit_warn_soft, audit_warn_hard);
278         if (err) {
279                 auditd_log_err("auditd_read_dirs(): %s",
280                     auditd_strerror(err));
281                 if (err == ADE_HARDLIM)
282                         audit_warn_allhard();
283                 if (err != ADE_SOFTLIM)
284                         return (-1);
285                 else
286                         audit_warn_allsoft();
287                         /* continue on with soft limit error */
288         }
289
290         /*
291          * Create a new file and swap with the one being used in kernel.
292          */
293         if (swap_audit_file() == -1) {
294                 /*
295                  * XXX Faulty directory listing? - user should be given
296                  * XXX an opportunity to change the audit_control file
297                  * XXX switch to a reduced mode of auditing?
298                  */
299                 return (-1);
300         }
301
302         /*
303          * Finally, see if there are any trail files to expire.
304          */
305         err = auditd_expire_trails(audit_warn_expired);
306         if (err)
307                 auditd_log_err("auditd_expire_trails(): %s",
308                     auditd_strerror(err));
309
310         return (0);
311 }
312
313 /*
314  * Start up auditing.
315  */
316 static void
317 audit_setup(void)
318 {
319         int err;
320
321         /* Configure trail files distribution. */
322         err = auditd_set_dist();
323         if (err) {
324                 auditd_log_err("auditd_set_dist() %s: %m",
325                     auditd_strerror(err));
326         } else
327                 auditd_log_debug("Configured trail files distribution.");
328
329         if (do_trail_file() == -1) {
330                 auditd_log_err("Error creating audit trail file");
331                 fail_exit();
332         }
333
334         /* Generate an audit record. */
335         err = auditd_gen_record(AUE_audit_startup, NULL);
336         if (err)
337                 auditd_log_err("auditd_gen_record(AUE_audit_startup) %s: %m",
338                     auditd_strerror(err));
339
340         if (auditd_config_controls() == 0)
341                 auditd_log_info("Audit controls init successful");
342         else
343                 auditd_log_err("Audit controls init failed");
344 }
345
346
347 /*
348  * Close auditd pid file and trigger mechanism.
349  */
350 static int
351 close_misc(void)
352 {
353
354         auditd_close_dirs();
355         if (unlink(AUDITD_PIDFILE) == -1 && errno != ENOENT) {
356                 auditd_log_err("Couldn't remove %s: %m", AUDITD_PIDFILE);
357                 return (1);
358         }
359         endac();
360
361         if (auditd_close_trigger() != 0) {
362                 auditd_log_err("Error closing trigger messaging mechanism");
363                 return (1);
364         }
365         return (0);
366 }
367
368 /*
369  * Close all log files, control files, and tell the audit system.
370  */
371 static int
372 close_all(void)
373 {
374         int err_ret = 0;
375         char TS[TIMESTAMP_LEN + 1];
376         int err;
377         int cond;
378         time_t tt;
379
380         err = auditd_gen_record(AUE_audit_shutdown, NULL);
381         if (err)
382                 auditd_log_err("auditd_gen_record(AUE_audit_shutdown) %s: %m",
383                     auditd_strerror(err));
384
385         /* Flush contents. */
386         cond = AUC_DISABLED;
387         err_ret = audit_set_cond(&cond);
388         if (err_ret != 0) {
389                 auditd_log_err("Disabling audit failed! : %s", strerror(errno));
390                 err_ret = 1;
391         }
392
393         /*
394          * Updated the cached state that auditing has been disabled.
395          */
396         auditd_set_state(AUD_STATE_DISABLED);
397
398         if (getTSstr(tt, TS, sizeof(TS)) == 0)
399                 close_lastfile(TS);
400         if (lastfile != NULL)
401                 free(lastfile);
402
403         err_ret += close_misc();
404
405         if (err_ret) {
406                 auditd_log_err("Could not unregister");
407                 audit_warn_postsigterm();
408         }
409
410         auditd_log_info("Finished");
411         return (err_ret);
412 }
413
414 /*
415  * Register the daemon with the signal handler and the auditd pid file.
416  */
417 static int
418 register_daemon(void)
419 {
420         FILE * pidfile;
421         int fd;
422         pid_t pid;
423
424         /* Set up the signal hander. */
425         if (signal(SIGTERM, auditd_relay_signal) == SIG_ERR) {
426                 auditd_log_err(
427                     "Could not set signal handler for SIGTERM");
428                 fail_exit();
429         }
430         if (signal(SIGCHLD, auditd_relay_signal) == SIG_ERR) {
431                 auditd_log_err(
432                     "Could not set signal handler for SIGCHLD");
433                 fail_exit();
434         }
435         if (signal(SIGHUP, auditd_relay_signal) == SIG_ERR) {
436                 auditd_log_err(
437                     "Could not set signal handler for SIGHUP");
438                 fail_exit();
439         }
440         if (signal(SIGALRM, auditd_relay_signal) == SIG_ERR) {
441                 auditd_log_err(
442                     "Could not set signal handler for SIGALRM");
443                 fail_exit();
444         }
445
446         if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) {
447                 auditd_log_err("Could not open PID file");
448                 audit_warn_tmpfile();
449                 return (-1);
450         }
451
452         /* Attempt to lock the pid file; if a lock is present, exit. */
453         fd = fileno(pidfile);
454         if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
455                 auditd_log_err(
456                     "PID file is locked (is another auditd running?).");
457                 audit_warn_ebusy();
458                 return (-1);
459         }
460
461         pid = getpid();
462         ftruncate(fd, 0);
463         if (fprintf(pidfile, "%u\n", pid) < 0) {
464                 /* Should not start the daemon. */
465                 fail_exit();
466         }
467
468         fflush(pidfile);
469         return (0);
470 }
471
472 /*
473  * Handle the audit trigger event.
474  *
475  * We suppress (ignore) duplicated triggers in close succession in order to
476  * try to avoid thrashing-like behavior.  However, not all triggers can be
477  * ignored, as triggers generally represent edge triggers, not level
478  * triggers, and won't be retransmitted if the condition persists.  Of
479  * specific concern is the rotate trigger -- if one is dropped, then it will
480  * not be retransmitted, and the log file will grow in an unbounded fashion.
481  */
482 #define DUPLICATE_INTERVAL      30
483 void
484 auditd_handle_trigger(int trigger)
485 {
486         static int last_trigger, last_warning;
487         static time_t last_time;
488         struct timeval ts;
489         struct timezone tzp;
490         time_t tt;
491         int au_state;
492         int err = 0;
493
494         /*
495          * Suppress duplicate messages from the kernel within the specified
496          * interval.
497          */
498         if (gettimeofday(&ts, &tzp) == 0) {
499                 tt = (time_t)ts.tv_sec;
500                 switch (trigger) {
501                 case AUDIT_TRIGGER_LOW_SPACE:
502                 case AUDIT_TRIGGER_NO_SPACE:
503                         /*
504                          * Triggers we can suppress.  Of course, we also need
505                          * to rate limit the warnings, so apply the same
506                          * interval limit on syslog messages.
507                          */
508                         if ((trigger == last_trigger) &&
509                             (tt < (last_time + DUPLICATE_INTERVAL))) {
510                                 if (tt >= (last_warning + DUPLICATE_INTERVAL))
511                                         auditd_log_info(
512                                             "Suppressing duplicate trigger %d",
513                                             trigger);
514                                 return;
515                         }
516                         last_warning = tt;
517                         break;
518
519                 case AUDIT_TRIGGER_ROTATE_KERNEL:
520                 case AUDIT_TRIGGER_ROTATE_USER:
521                 case AUDIT_TRIGGER_READ_FILE:
522                 case AUDIT_TRIGGER_CLOSE_AND_DIE:
523                 case AUDIT_TRIGGER_INITIALIZE:
524                         /*
525                          * Triggers that we cannot suppress.
526                          */
527                         break;
528                 }
529
530                 /*
531                  * Only update last_trigger after aborting due to a duplicate
532                  * trigger, not before, or we will never allow that trigger
533                  * again.
534                  */
535                 last_trigger = trigger;
536                 last_time = tt;
537         }
538
539         au_state = auditd_get_state();
540
541         /*
542          * Message processing is done here.
543          */
544         switch(trigger) {
545         case AUDIT_TRIGGER_LOW_SPACE:
546                 auditd_log_notice("Got low space trigger");
547                 if (do_trail_file() == -1)
548                         auditd_log_err("Error swapping audit file");
549                 break;
550
551         case AUDIT_TRIGGER_NO_SPACE:
552                 auditd_log_notice("Got no space trigger");
553                 if (do_trail_file() == -1)
554                         auditd_log_err("Error swapping audit file");
555                 break;
556
557         case AUDIT_TRIGGER_ROTATE_KERNEL:
558         case AUDIT_TRIGGER_ROTATE_USER:
559                 auditd_log_info("Got open new trigger from %s", trigger ==
560                     AUDIT_TRIGGER_ROTATE_KERNEL ? "kernel" : "user");
561                 if (au_state == AUD_STATE_ENABLED && do_trail_file() == -1)
562                         auditd_log_err("Error swapping audit file");
563                 break;
564
565         case AUDIT_TRIGGER_READ_FILE:
566                 auditd_log_info("Got read file trigger");
567                 if (au_state == AUD_STATE_ENABLED) {
568                         if (auditd_config_controls() == -1)
569                                 auditd_log_err("Error setting audit controls");
570                         else if (do_trail_file() == -1)
571                                 auditd_log_err("Error swapping audit file");
572                 }
573                 break;
574
575         case AUDIT_TRIGGER_CLOSE_AND_DIE:
576                 auditd_log_info("Got close and die trigger");
577                 if (au_state == AUD_STATE_ENABLED)
578                         err = close_all();
579                 /*
580                  * Running under launchd don't exit.  Wait for launchd to
581                  * send SIGTERM.
582                  */
583                 if (!launchd_flag) {
584                         auditd_log_info("auditd exiting.");
585                         exit (err);
586                 }
587                 break;
588
589         case AUDIT_TRIGGER_INITIALIZE:
590                 auditd_log_info("Got audit initialize trigger");
591                 if (au_state == AUD_STATE_DISABLED)
592                         audit_setup();
593                 break;
594
595         case AUDIT_TRIGGER_EXPIRE_TRAILS:
596                 auditd_log_info("Got audit expire trails trigger");
597                 err = auditd_expire_trails(audit_warn_expired);
598                 if (err)
599                         auditd_log_err("auditd_expire_trails(): %s",
600                             auditd_strerror(err));
601                 break;
602
603         default:
604                 auditd_log_err("Got unknown trigger %d", trigger);
605                 break;
606         }
607 }
608
609 /*
610  * Reap our children.
611  */
612 void
613 auditd_reap_children(void)
614 {
615         pid_t child;
616         int wstatus;
617
618         while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) {
619                 if (!wstatus)
620                         continue;
621                 auditd_log_info("warn process [pid=%d] %s %d.", child,
622                     ((WIFEXITED(wstatus)) ? "exited with non-zero status" :
623                     "exited as a result of signal"),
624                     ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) :
625                     WTERMSIG(wstatus)));
626         }
627 }
628
629 /*
630  * Reap any children and terminate.  If under launchd don't shutdown auditing
631  * but just the other stuff.
632  */
633 void
634 auditd_terminate(void)
635 {
636         int ret;
637
638         auditd_reap_children();
639
640         if (launchd_flag)
641                 ret = close_misc();
642         else
643                 ret = close_all();
644
645         exit(ret);
646 }
647
648 /*
649  * Configure the audit controls in the kernel: the event to class mapping,
650  * kernel preselection mask, etc.
651  */
652 int
653 auditd_config_controls(void)
654 {
655         int cnt, err;
656         int ret = 0;
657
658         /*
659          * Configure event to class mappings in kernel.
660          */
661         cnt = auditd_set_evcmap();
662         if (cnt < 0) {
663                 auditd_log_err("auditd_set_evcmap() failed: %m");
664                 ret = -1;
665         } else if (cnt == 0) {
666                 auditd_log_err("No events to class mappings registered.");
667                 ret = -1;
668         } else
669                 auditd_log_debug("Registered %d event to class mappings.", cnt);
670
671         /*
672          * Configure non-attributable event mask in kernel.
673          */
674         err = auditd_set_namask();
675         if (err) {
676                 auditd_log_err("auditd_set_namask() %s: %m",
677                     auditd_strerror(err));
678                 ret = -1;
679         } else
680                 auditd_log_debug("Registered non-attributable event mask.");
681
682         /*
683          * Configure audit policy in kernel.
684          */
685         err = auditd_set_policy();
686         if (err) {
687                 auditd_log_err("auditd_set_policy() %s: %m",
688                     auditd_strerror(err));
689                 ret = -1;
690         } else
691                 auditd_log_debug("Set audit policy in kernel.");
692
693         /*
694          * Configure audit trail log size in kernel.
695          */
696         err = auditd_set_fsize();
697         if (err) {
698                 auditd_log_err("audit_set_fsize() %s: %m",
699                     auditd_strerror(err));
700                 ret = -1;
701         } else
702                 auditd_log_debug("Set audit trail size in kernel.");
703
704         /*
705          * Configure audit trail volume minimum free percentage of blocks in
706          * kernel.
707          */
708         err = auditd_set_minfree();
709         if (err) {
710                 auditd_log_err("auditd_set_minfree() %s: %m",
711                     auditd_strerror(err));
712                 ret = -1;
713         } else
714                 auditd_log_debug(
715                     "Set audit trail min free percent in kernel.");
716
717         /*
718          * Configure host address in the audit kernel information.
719          */
720         err = auditd_set_host();
721         if (err) {
722                 if (err == ADE_PARSE) {
723                         auditd_log_notice(
724                             "audit_control(5) may be missing 'host:' field");
725                 } else {
726                         auditd_log_err("auditd_set_host() %s: %m",
727                             auditd_strerror(err));
728                         ret = -1;
729                 }
730         } else
731                 auditd_log_debug(
732                     "Set audit host address information in kernel.");
733
734         return (ret);
735 }
736
737 /*
738  * Setup and initialize auditd.
739  */
740 static void
741 setup(void)
742 {
743         int err;
744
745         if (auditd_open_trigger(launchd_flag) < 0) {
746                 auditd_log_err("Error opening trigger messaging mechanism");
747                 fail_exit();
748         }
749
750         /*
751          * To prevent event feedback cycles and avoid auditd becoming
752          * stalled if auditing is suspended, auditd and its children run
753          * without their events being audited.  We allow the uid, tid, and
754          * mask fields to be implicitly set to zero, but do set the pid.  We
755          * run this after opening the trigger device to avoid configuring
756          * audit state without audit present in the system.
757          */
758         err = auditd_prevent_audit();
759         if (err) {
760                 auditd_log_err("auditd_prevent_audit() %s: %m",
761                     auditd_strerror(err));
762                 fail_exit();
763         }
764
765         /*
766          * Make sure auditd auditing state is correct.
767          */
768         auditd_set_state(AUD_STATE_INIT);
769
770         /*
771          * If under launchd, don't start auditing.  Wait for a trigger to
772          * do so.
773          */
774         if (!launchd_flag)
775                 audit_setup();
776 }
777
778 int
779 main(int argc, char **argv)
780 {
781         int ch;
782         int debug = 0;
783 #ifdef AUDIT_REVIEW_GROUP
784         struct group *grp;
785 #endif
786
787         while ((ch = getopt(argc, argv, "dl")) != -1) {
788                 switch(ch) {
789                 case 'd':
790                         /* Debug option. */
791                         debug = 1;
792                         break;
793
794                 case 'l':
795                         /* Be launchd friendly. */
796                         launchd_flag = 1;
797                         break;
798
799                 case '?':
800                 default:
801                         (void)fprintf(stderr,
802                             "usage: auditd [-d] [-l]\n");
803                         exit(1);
804                 }
805         }
806
807         audit_review_gid = getgid();
808
809 #ifdef AUDIT_REVIEW_GROUP
810         /*
811          * XXXRW: Currently, this code falls back to the daemon gid, which is
812          * likely the wheel group.  Is there a better way to deal with this?
813          */
814         grp = getgrnam(AUDIT_REVIEW_GROUP);
815         if (grp != NULL)
816                 audit_review_gid = grp->gr_gid;
817 #endif
818
819         auditd_openlog(debug, audit_review_gid);
820
821         if (launchd_flag)
822                 auditd_log_info("started by launchd...");
823         else
824                 auditd_log_info("starting...");
825
826 #ifdef AUDIT_REVIEW_GROUP
827         if (grp == NULL)
828                 auditd_log_info(
829                     "Audit review group '%s' not available, using daemon gid (%d)",
830                     AUDIT_REVIEW_GROUP, audit_review_gid);
831 #endif
832         if (debug == 0 && launchd_flag == 0 && daemon(0, 0) == -1) {
833                 auditd_log_err("Failed to daemonize");
834                 exit(1);
835         }
836
837         if (register_daemon() == -1) {
838                 auditd_log_err("Could not register as daemon");
839                 exit(1);
840         }
841
842         setup();
843
844         /*
845          * auditd_wait_for_events() shouldn't return unless something is wrong.
846          */
847         auditd_wait_for_events();
848
849         auditd_log_err("abnormal exit.");
850         close_all();
851         exit(-1);
852 }