]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - contrib/openbsm/bin/auditd/auditd.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.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#46 $
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         size_t len;
159
160         /* If lastfile is NULL try to get it from the 'current' link.  */
161         if (lastfile == NULL)
162                 lastfile = get_curfile();
163         
164         if (lastfile != NULL) {
165                 len = strlen(lastfile) + 1;
166                 oldname = (char *)malloc(len);
167                 if (oldname == NULL)
168                         return (-1);
169                 strlcpy(oldname, lastfile, len);
170
171                 /* Rename the last file -- append timestamp. */
172                 if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) {
173                         memcpy(ptr, TS, POSTFIX_LEN);
174                         if (rename(oldname, lastfile) != 0)
175                                 auditd_log_err(
176                                     "Could not rename %s to %s: %m", oldname,
177                                     lastfile);
178                         else {
179                                 /* 
180                                  * Remove the 'current' symlink since the link
181                                  * is now invalid. 
182                                  */
183                                 (void) unlink(AUDIT_CURRENT_LINK);
184                                 auditd_log_notice( "renamed %s to %s",
185                                     oldname, lastfile);
186                                 audit_warn_closefile(lastfile);
187                         }
188                 } else 
189                         auditd_log_err( "Could not rename %s to %s", oldname,
190                             lastfile);
191                 free(lastfile);
192                 free(oldname);
193                 lastfile = NULL;
194         }
195         return (0);
196 }
197
198 /*
199  * Create the new file name, swap with existing audit file.
200  */
201 static int
202 swap_audit_file(void)
203 {
204         int err;
205         char *newfile;
206         char TS[TIMESTAMP_LEN];
207         time_t tt;
208
209         if (getTSstr(tt, TS, TIMESTAMP_LEN) != 0)
210                 return (-1);
211         err = auditd_swap_trail(TS, &newfile, audit_review_gid,
212             audit_warn_getacdir);
213         if (err != ADE_NOERR) {
214                 auditd_log_err( "%s: %m", auditd_strerror(err));
215                 if (err != ADE_ACTL)
216                         return (-1);
217         }
218
219         /*
220          * Only close the last file if were in an auditing state before
221          * calling swap_audit_file().  We may need to recover from a crash.
222          */
223         if (auditd_get_state() == AUD_STATE_ENABLED)
224                 close_lastfile(TS);
225
226
227         /*
228          * auditd_swap_trail() potentially enables auditing (if not already
229          * enabled) so updated the cached state as well.
230          */
231         auditd_set_state(AUD_STATE_ENABLED);
232         
233         /*
234          *  Create 'current' symlink.  Recover from crash, if needed.
235          */
236         if (auditd_new_curlink(newfile) != 0)
237                 auditd_log_err("auditd_new_curlink(\"%s\") failed: %s: %m",
238                      newfile, auditd_strerror(err)); 
239
240         lastfile = newfile;
241         auditd_log_notice("New audit file is %s", newfile);
242
243         return (0);
244 }
245
246 /*
247  * Create a new audit log trail file and swap with the current one, if any.
248  */
249 static int
250 do_trail_file(void)
251 {
252         int err;
253
254         /*
255          * First, refresh the list of audit log directories.
256          */
257         err = auditd_read_dirs(audit_warn_soft, audit_warn_hard);
258         if (err) {
259                 auditd_log_err("auditd_read_dirs(): %s",
260                     auditd_strerror(err));
261                 if (err == ADE_HARDLIM)
262                         audit_warn_allhard();
263                 if (err != ADE_SOFTLIM)
264                         return (-1);
265                 else
266                         audit_warn_allsoft();
267                         /* continue on with soft limit error */
268         }
269
270         /*
271          * Create a new file and swap with the one being used in kernel.
272          */
273         if (swap_audit_file() == -1) {
274                 /*
275                  * XXX Faulty directory listing? - user should be given
276                  * XXX an opportunity to change the audit_control file
277                  * XXX switch to a reduced mode of auditing?
278                  */
279                 return (-1);
280         }
281
282         /*
283          * Finally, see if there are any trail files to expire.
284          */
285         err = auditd_expire_trails(audit_warn_expired);
286         if (err)
287                 auditd_log_err("auditd_expire_trails(): %s",
288                     auditd_strerror(err));
289
290         return (0);
291 }
292
293 /*
294  * Start up auditing.
295  */
296 static void
297 audit_setup(void)
298 {
299         int err;
300
301         if (do_trail_file() == -1) {
302                 auditd_log_err("Error creating audit trail file");
303                 fail_exit();
304         }
305
306         /* Generate an audit record. */
307         err = auditd_gen_record(AUE_audit_startup, NULL);
308         if (err)
309                 auditd_log_err("auditd_gen_record(AUE_audit_startup) %s: %m", 
310                     auditd_strerror(err));
311         
312         if (auditd_config_controls() == 0)
313                 auditd_log_info("Audit controls init successful");
314         else
315                 auditd_log_err("Audit controls init failed");
316         
317 }
318
319
320 /*
321  * Close auditd pid file and trigger mechanism. 
322  */
323 static int
324 close_misc(void)
325 {
326
327         auditd_close_dirs();
328         if (unlink(AUDITD_PIDFILE) == -1 && errno != ENOENT) {
329                 auditd_log_err("Couldn't remove %s: %m", AUDITD_PIDFILE);
330                 return (1);
331         }
332         endac();
333
334         if (auditd_close_trigger() != 0) {
335                 auditd_log_err("Error closing trigger messaging mechanism");
336                 return (1);
337         }
338         return (0);
339 }
340
341 /*
342  * Close all log files, control files, and tell the audit system.
343  */
344 static int
345 close_all(void)
346 {
347         int err_ret = 0;
348         char TS[TIMESTAMP_LEN];
349         int err;
350         int cond;
351         time_t tt;
352
353         err = auditd_gen_record(AUE_audit_shutdown, NULL);
354         if (err)
355                 auditd_log_err("auditd_gen_record(AUE_audit_shutdown) %s: %m", 
356                     auditd_strerror(err));
357
358         /* Flush contents. */
359         cond = AUC_DISABLED;
360         err_ret = audit_set_cond(&cond);
361         if (err_ret != 0) {
362                 auditd_log_err("Disabling audit failed! : %s", strerror(errno));
363                 err_ret = 1;
364         }
365
366         /*
367          * Updated the cached state that auditing has been disabled.
368          */
369         auditd_set_state(AUD_STATE_DISABLED);
370
371         if (getTSstr(tt, TS, TIMESTAMP_LEN) == 0)
372                 close_lastfile(TS);
373         if (lastfile != NULL)
374                 free(lastfile);
375
376         err_ret += close_misc();
377
378         if (err_ret) {
379                 auditd_log_err("Could not unregister");
380                 audit_warn_postsigterm();
381         }
382
383         auditd_log_info("Finished");
384         return (err_ret);
385 }
386
387 /*
388  * Register the daemon with the signal handler and the auditd pid file.
389  */
390 static int
391 register_daemon(void)
392 {
393         FILE * pidfile;
394         int fd;
395         pid_t pid;
396
397         /* Set up the signal hander. */
398         if (signal(SIGTERM, auditd_relay_signal) == SIG_ERR) {
399                 auditd_log_err(
400                     "Could not set signal handler for SIGTERM");
401                 fail_exit();
402         }
403         if (signal(SIGCHLD, auditd_relay_signal) == SIG_ERR) {
404                 auditd_log_err(
405                     "Could not set signal handler for SIGCHLD");
406                 fail_exit();
407         }
408         if (signal(SIGHUP, auditd_relay_signal) == SIG_ERR) {
409                 auditd_log_err(
410                     "Could not set signal handler for SIGHUP");
411                 fail_exit();
412         }
413         if (signal(SIGALRM, auditd_relay_signal) == SIG_ERR) {
414                 auditd_log_err(
415                     "Could not set signal handler for SIGALRM");
416                 fail_exit();
417         }
418
419         if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) {
420                 auditd_log_err("Could not open PID file");
421                 audit_warn_tmpfile();
422                 return (-1);
423         }
424
425         /* Attempt to lock the pid file; if a lock is present, exit. */
426         fd = fileno(pidfile);
427         if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
428                 auditd_log_err(
429                     "PID file is locked (is another auditd running?).");
430                 audit_warn_ebusy();
431                 return (-1);
432         }
433
434         pid = getpid();
435         ftruncate(fd, 0);
436         if (fprintf(pidfile, "%u\n", pid) < 0) {
437                 /* Should not start the daemon. */
438                 fail_exit();
439         }
440
441         fflush(pidfile);
442         return (0);
443 }
444
445 /*
446  * Handle the audit trigger event.
447  *
448  * We suppress (ignore) duplicated triggers in close succession in order to
449  * try to avoid thrashing-like behavior.  However, not all triggers can be
450  * ignored, as triggers generally represent edge triggers, not level
451  * triggers, and won't be retransmitted if the condition persists.  Of
452  * specific concern is the rotate trigger -- if one is dropped, then it will
453  * not be retransmitted, and the log file will grow in an unbounded fashion.
454  */
455 #define DUPLICATE_INTERVAL      30
456 void
457 auditd_handle_trigger(int trigger)
458 {
459         static int last_trigger, last_warning;
460         static time_t last_time;
461         struct timeval ts;
462         struct timezone tzp;
463         time_t tt;
464         int au_state;
465         int err = 0;
466
467         /*
468          * Suppress duplicate messages from the kernel within the specified
469          * interval.
470          */
471         if (gettimeofday(&ts, &tzp) == 0) {
472                 tt = (time_t)ts.tv_sec;
473                 switch (trigger) {
474                 case AUDIT_TRIGGER_LOW_SPACE:
475                 case AUDIT_TRIGGER_NO_SPACE:
476                         /*
477                          * Triggers we can suppress.  Of course, we also need
478                          * to rate limit the warnings, so apply the same
479                          * interval limit on syslog messages.
480                          */
481                         if ((trigger == last_trigger) &&
482                             (tt < (last_time + DUPLICATE_INTERVAL))) {
483                                 if (tt >= (last_warning + DUPLICATE_INTERVAL))
484                                         auditd_log_info(
485                                             "Suppressing duplicate trigger %d",
486                                             trigger);
487                                 return;
488                         }
489                         last_warning = tt;
490                         break;
491
492                 case AUDIT_TRIGGER_ROTATE_KERNEL:
493                 case AUDIT_TRIGGER_ROTATE_USER:
494                 case AUDIT_TRIGGER_READ_FILE:
495                 case AUDIT_TRIGGER_CLOSE_AND_DIE:
496                 case AUDIT_TRIGGER_INITIALIZE:
497                         /*
498                          * Triggers that we cannot suppress.
499                          */
500                         break;
501                 }
502
503                 /*
504                  * Only update last_trigger after aborting due to a duplicate
505                  * trigger, not before, or we will never allow that trigger
506                  * again.
507                  */
508                 last_trigger = trigger;
509                 last_time = tt;
510         }
511
512         au_state = auditd_get_state();
513
514         /*
515          * Message processing is done here.
516          */
517         switch(trigger) {
518         case AUDIT_TRIGGER_LOW_SPACE:
519                 auditd_log_notice("Got low space trigger");
520                 if (do_trail_file() == -1)
521                         auditd_log_err("Error swapping audit file");
522                 break;
523
524         case AUDIT_TRIGGER_NO_SPACE:
525                 auditd_log_notice("Got no space trigger");
526                 if (do_trail_file() == -1)
527                         auditd_log_err("Error swapping audit file");
528                 break;
529
530         case AUDIT_TRIGGER_ROTATE_KERNEL:
531         case AUDIT_TRIGGER_ROTATE_USER:
532                 auditd_log_info("Got open new trigger from %s", trigger ==
533                     AUDIT_TRIGGER_ROTATE_KERNEL ? "kernel" : "user");
534                 if (au_state == AUD_STATE_ENABLED && do_trail_file() == -1)
535                         auditd_log_err("Error swapping audit file");
536                 break;
537
538         case AUDIT_TRIGGER_READ_FILE:
539                 auditd_log_info("Got read file trigger");
540                 if (au_state == AUD_STATE_ENABLED) {
541                         if (auditd_config_controls() == -1)
542                                 auditd_log_err("Error setting audit controls");
543                         else if (do_trail_file() == -1)
544                                 auditd_log_err("Error swapping audit file");
545                 }
546                 break;
547
548         case AUDIT_TRIGGER_CLOSE_AND_DIE:
549                 auditd_log_info("Got close and die trigger");
550                 if (au_state == AUD_STATE_ENABLED)
551                         err = close_all();
552                 /*
553                  * Running under launchd don't exit.  Wait for launchd to
554                  * send SIGTERM.
555                  */
556                 if (!launchd_flag) {
557                         auditd_log_info("auditd exiting.");     
558                         exit (err);
559                 }
560                 break;
561
562         case AUDIT_TRIGGER_INITIALIZE:
563                 auditd_log_info("Got audit initialize trigger");
564                 if (au_state == AUD_STATE_DISABLED)
565                         audit_setup();
566                 break;
567
568         case AUDIT_TRIGGER_EXPIRE_TRAILS:
569                 auditd_log_info("Got audit expire trails trigger");
570                 err = auditd_expire_trails(audit_warn_expired);
571                 if (err)
572                         auditd_log_err("auditd_expire_trails(): %s",
573                             auditd_strerror(err));
574                 break;
575
576         default:
577                 auditd_log_err("Got unknown trigger %d", trigger);
578                 break;
579         }
580 }
581
582 /*
583  * Reap our children.
584  */
585 void
586 auditd_reap_children(void)
587 {
588         pid_t child;
589         int wstatus;
590
591         while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) {
592                 if (!wstatus)
593                         continue;
594                 auditd_log_info("warn process [pid=%d] %s %d.", child,
595                     ((WIFEXITED(wstatus)) ? "exited with non-zero status" :
596                     "exited as a result of signal"),
597                     ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) :
598                     WTERMSIG(wstatus)));
599         }
600 }
601
602 /*
603  * Reap any children and terminate.  If under launchd don't shutdown auditing
604  * but just the other stuff.
605  */
606 void
607 auditd_terminate(void)
608 {
609         int ret;
610
611         auditd_reap_children();
612         
613         if (launchd_flag)
614                 ret = close_misc();
615         else
616                 ret = close_all();
617
618         exit(ret);
619 }
620
621 /*
622  * Configure the audit controls in the kernel: the event to class mapping,
623  * kernel preselection mask, etc.
624  */
625 int
626 auditd_config_controls(void)
627 {
628         int cnt, err;
629         int ret = 0;
630
631         /*
632          * Configure event to class mappings in kernel.
633          */     
634         cnt = auditd_set_evcmap();
635         if (cnt < 0) {
636                 auditd_log_err("auditd_set_evcmap() failed: %m");
637                 ret = -1;
638         } else if (cnt == 0) {
639                 auditd_log_err("No events to class mappings registered.");
640                 ret = -1;
641         } else
642                 auditd_log_debug("Registered %d event to class mappings.", cnt);
643
644         /*
645          * Configure non-attributable event mask in kernel.
646          */
647         err = auditd_set_namask();
648         if (err) {
649                 auditd_log_err("auditd_set_namask() %s: %m", 
650                     auditd_strerror(err));
651                 ret = -1;
652         } else
653                 auditd_log_debug("Registered non-attributable event mask.");
654
655         /*
656          * Configure audit policy in kernel.
657          */
658         err = auditd_set_policy();
659         if (err) {
660                 auditd_log_err("auditd_set_policy() %s: %m", 
661                     auditd_strerror(err));
662                 ret = -1;
663         } else
664                 auditd_log_debug("Set audit policy in kernel.");
665         
666         /*
667          * Configure audit trail log size in kernel.
668          */
669         err = auditd_set_fsize();
670         if (err) {
671                 auditd_log_err("audit_set_fsize() %s: %m",
672                     auditd_strerror(err));
673                 ret = -1;
674         } else
675                 auditd_log_debug("Set audit trail size in kernel.");
676         
677         /*
678          * Configure audit trail volume minimum free percentage of blocks in 
679          * kernel.
680          */
681         err = auditd_set_minfree();
682         if (err) {
683                 auditd_log_err("auditd_set_minfree() %s: %m",
684                     auditd_strerror(err));
685                 ret = -1;
686         } else
687                 auditd_log_debug( 
688                     "Set audit trail min free percent in kernel.");
689
690         /*
691          * Configure host address in the audit kernel information. 
692          */
693         err = auditd_set_host();
694         if (err) {
695                 if (err == ADE_PARSE) {
696                         auditd_log_notice(
697                             "audit_control(5) may be missing 'host:' field");
698                 } else {
699                         auditd_log_err("auditd_set_host() %s: %m",
700                             auditd_strerror(err));
701                         ret = -1;
702                 }
703         } else
704                 auditd_log_debug(
705                     "Set audit host address information in kernel.");
706
707         return (ret);
708 }
709
710 /*
711  * Setup and initialize auditd.
712  */
713 static void
714 setup(void)
715 {
716         int err;
717
718         if (auditd_open_trigger(launchd_flag) < 0) {
719                 auditd_log_err("Error opening trigger messaging mechanism");
720                 fail_exit();
721         }
722
723         /*
724          * To prevent event feedback cycles and avoid auditd becoming
725          * stalled if auditing is suspended, auditd and its children run
726          * without their events being audited.  We allow the uid, tid, and
727          * mask fields to be implicitly set to zero, but do set the pid.  We
728          * run this after opening the trigger device to avoid configuring
729          * audit state without audit present in the system.
730          */
731         err = auditd_prevent_audit();
732         if (err) {
733                 auditd_log_err("auditd_prevent_audit() %s: %m", 
734                     auditd_strerror(err));
735                 fail_exit();
736         }
737
738         /*
739          * Make sure auditd auditing state is correct.
740          */
741         auditd_set_state(AUD_STATE_INIT);
742
743         /*
744          * If under launchd, don't start auditing.  Wait for a trigger to
745          * do so.
746          */
747         if (!launchd_flag)
748                 audit_setup();
749 }
750
751 int
752 main(int argc, char **argv)
753 {
754         int ch;
755         int debug = 0;
756 #ifdef AUDIT_REVIEW_GROUP
757         struct group *grp;
758 #endif
759
760         while ((ch = getopt(argc, argv, "dl")) != -1) {
761                 switch(ch) {
762                 case 'd':
763                         /* Debug option. */
764                         debug = 1;
765                         break;
766
767                 case 'l':
768                         /* Be launchd friendly. */
769                         launchd_flag = 1;
770                         break;
771
772                 case '?':
773                 default:
774                         (void)fprintf(stderr,
775                             "usage: auditd [-d] [-l]\n");
776                         exit(1);
777                 }
778         }
779
780         audit_review_gid = getgid();
781
782 #ifdef AUDIT_REVIEW_GROUP
783         /*
784          * XXXRW: Currently, this code falls back to the daemon gid, which is
785          * likely the wheel group.  Is there a better way to deal with this?
786          */
787         grp = getgrnam(AUDIT_REVIEW_GROUP);
788         if (grp != NULL) 
789                 audit_review_gid = grp->gr_gid;
790 #endif
791
792         auditd_openlog(debug, audit_review_gid);
793
794         if (launchd_flag)
795                 auditd_log_info("started by launchd...");
796         else
797                 auditd_log_info("starting...");
798
799 #ifdef AUDIT_REVIEW_GROUP
800         if (grp == NULL)
801                 auditd_log_info(
802                     "Audit review group '%s' not available, using daemon gid (%d)",
803                     AUDIT_REVIEW_GROUP, audit_review_gid);
804 #endif
805         if (debug == 0 && launchd_flag == 0 && daemon(0, 0) == -1) {
806                 auditd_log_err("Failed to daemonize");
807                 exit(1);
808         }
809
810         if (register_daemon() == -1) {
811                 auditd_log_err("Could not register as daemon");
812                 exit(1);
813         }
814
815         setup();
816
817         /*
818          * auditd_wait_for_events() shouldn't return unless something is wrong. 
819          */
820         auditd_wait_for_events();
821
822         auditd_log_err("abnormal exit.");
823         close_all();
824         exit(-1);
825 }