]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/openbsm/bin/auditd/auditd.c
This commit was generated by cvs2svn to compensate for changes in r157001,
[FreeBSD/FreeBSD.git] / contrib / openbsm / bin / auditd / auditd.c
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#13 $
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 <errno.h>
48 #include <fcntl.h>
49 #include <grp.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <time.h>
53 #include <unistd.h>
54 #include <signal.h>
55 #include <string.h>
56 #include <syslog.h>
57
58 #include "auditd.h"
59
60 #define NA_EVENT_STR_SIZE       25
61
62 static int       ret, minval;
63 static char     *lastfile = NULL;
64 static int       allhardcount = 0;
65 static int       triggerfd = 0;
66 static int       sighups, sighups_handled;
67 static int       sigterms, sigterms_handled;
68 static long      global_flags;
69
70 static TAILQ_HEAD(, dir_ent)    dir_q;
71
72 static int      config_audit_controls(void);
73
74 /*
75  * Error starting auditd
76  */
77 static void
78 fail_exit(void)
79 {
80
81         audit_warn_nostart();
82         exit(1);
83 }
84
85 /*
86  * Free our local list of directory names.
87  */
88 static void
89 free_dir_q()
90 {
91         struct dir_ent *dirent;
92
93         while ((dirent = TAILQ_FIRST(&dir_q))) {
94                 TAILQ_REMOVE(&dir_q, dirent, dirs);
95                 free(dirent->dirname);
96                 free(dirent);
97         }
98 }
99
100 /*
101  * Generate the timestamp string.
102  */
103 static int
104 getTSstr(char *buf, int len)
105 {
106         struct timeval ts;
107         struct timezone tzp;
108         time_t tt;
109
110         if (gettimeofday(&ts, &tzp) != 0)
111                 return (-1);
112         tt = (time_t)ts.tv_sec;
113         if (!strftime(buf, len, "%Y%m%d%H%M%S", gmtime(&tt)))
114                 return (-1);
115         return (0);
116 }
117
118 /*
119  * Concat the directory name to the given file name.
120  * XXX We should affix the hostname also
121  */
122 static char *
123 affixdir(char *name, struct dir_ent *dirent)
124 {
125         char *fn;
126         char *curdir;
127         const char *sep = "/";
128
129         curdir = dirent->dirname;
130         syslog(LOG_INFO, "dir = %s\n", dirent->dirname);
131
132         fn = malloc(strlen(curdir) + strlen(sep) + (2 * POSTFIX_LEN) + 1);
133         if (fn == NULL)
134                 return (NULL);
135         strcpy(fn, curdir);
136         strcat(fn, sep);
137         strcat(fn, name);
138         return (fn);
139 }
140
141 /*
142  * Close the previous audit trail file.
143  */
144 static int
145 close_lastfile(char *TS)
146 {
147         char *ptr;
148         char *oldname;
149
150         if (lastfile != NULL) {
151                 oldname = (char *)malloc(strlen(lastfile) + 1);
152                 if (oldname == NULL)
153                         return (-1);
154                 strcpy(oldname, lastfile);
155
156                 /* Rename the last file -- append timestamp. */
157                 if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) {
158                         *ptr = '.';
159                         strcpy(ptr+1, TS);
160                         if (rename(oldname, lastfile) != 0)
161                                 syslog(LOG_ERR, "Could not rename %s to %s \n",
162                                     oldname, lastfile);
163                         else
164                                 syslog(LOG_INFO, "renamed %s to %s \n",
165                                     oldname, lastfile);
166                 }
167                 free(lastfile);
168                 free(oldname);
169                 lastfile = NULL;
170         }
171         return (0);
172 }
173
174 /*
175  * Create the new audit file with appropriate permissions and ownership.  Try
176  * to clean up if something goes wrong.
177  */
178 static int
179 #ifdef AUDIT_REVIEW_GROUP
180 open_trail(const char *fname, uid_t uid, gid_t gid)
181 #else
182 open_trail(const char *fname)
183 #endif
184 {
185         int error, fd;
186
187         fd = open(fname, O_RDONLY | O_CREAT, S_IRUSR | S_IRGRP);
188         if (fd < 0)
189                 return (-1);
190 #ifdef AUDIT_REVIEW_GROUP
191         if (fchown(fd, uid, gid) < 0) {
192                 error = errno;
193                 close(fd);
194                 (void)unlink(fname);
195                 errno = error;
196                 return (-1);
197         }
198 #endif
199         return (fd);
200 }
201
202 /*
203  * Create the new file name, swap with existing audit file.
204  */
205 static int
206 swap_audit_file(void)
207 {
208         char timestr[2 * POSTFIX_LEN];
209         char *fn;
210         char TS[POSTFIX_LEN];
211         struct dir_ent *dirent;
212 #ifdef AUDIT_REVIEW_GROUP
213         struct group *grp;
214         gid_t gid;
215         uid_t uid;
216 #endif
217         int error, fd;
218
219         if (getTSstr(TS, POSTFIX_LEN) != 0)
220                 return (-1);
221
222         strcpy(timestr, TS);
223         strcat(timestr, NOT_TERMINATED);
224
225 #ifdef AUDIT_REVIEW_GROUP
226         /*
227          * XXXRW: Currently, this code falls back to the daemon gid, which is
228          * likely the wheel group.  Is there a better way to deal with this?
229          */
230         grp = getgrnam(AUDIT_REVIEW_GROUP);
231         if (grp == NULL) {
232                 syslog(LOG_INFO,
233                     "Audit review group '%s' not available, using daemon gid",
234                     AUDIT_REVIEW_GROUP);
235                 gid = -1;
236         } else
237                 gid = grp->gr_gid;
238         uid = getuid();
239 #endif
240
241         /* Try until we succeed. */
242         while ((dirent = TAILQ_FIRST(&dir_q))) {
243                 if ((fn = affixdir(timestr, dirent)) == NULL) {
244                         syslog(LOG_INFO, "Failed to swap log  at time %s\n",
245                                 timestr);
246                         return (-1);
247                 }
248
249                 /*
250                  * Create and open the file; then close and pass to the
251                  * kernel if all went well.
252                  */
253                 syslog(LOG_INFO, "New audit file is %s\n", fn);
254 #ifdef AUDIT_REVIEW_GROUP
255                 fd = open_trail(fn, uid, gid);
256 #else
257                 fd = open_trail(fn);
258 #endif
259                 if (fd < 0)
260                         warn("open(%s)", fn);
261                 if (fd >= 0) {
262                         error = auditctl(fn);
263                         if (error) {
264                                 syslog(LOG_ERR,
265                                     "auditctl failed setting log file! : %s\n",
266                                     strerror(errno));
267                                 close(fd);
268                         } else {
269                                 /* Success. */
270                                 close_lastfile(TS);
271                                 lastfile = fn;
272                                 close(fd);
273                                 return (0);
274                         }
275                 }
276
277                 /*
278                  * Tell the administrator about lack of permissions for dir.
279                  */
280                 audit_warn_getacdir(dirent->dirname);
281
282                 /* Try again with a different directory. */
283                 TAILQ_REMOVE(&dir_q, dirent, dirs);
284                 free(dirent->dirname);
285                 free(dirent);
286         }
287         syslog(LOG_INFO, "Log directories exhausted\n");
288         return (-1);
289 }
290
291 /*
292  * Read the audit_control file contents.
293  */
294 static int
295 read_control_file(void)
296 {
297         char cur_dir[MAXNAMLEN];
298         struct dir_ent *dirent;
299         au_qctrl_t qctrl;
300
301         /*
302          * Clear old values.  Force a re-read of the file the next time.
303          */
304         free_dir_q();
305         endac();
306
307         /*
308          * Read the list of directories into a local linked list.
309          *
310          * XXX We should use the reentrant interfaces once they are
311          * available.
312          */
313         while (getacdir(cur_dir, MAXNAMLEN) >= 0) {
314                 dirent = (struct dir_ent *) malloc(sizeof(struct dir_ent));
315                 if (dirent == NULL)
316                         return (-1);
317                 dirent->softlim = 0;
318                 dirent->dirname = (char *) malloc(MAXNAMLEN);
319                 if (dirent->dirname == NULL) {
320                         free(dirent);
321                         return (-1);
322                 }
323                 strcpy(dirent->dirname, cur_dir);
324                 TAILQ_INSERT_TAIL(&dir_q, dirent, dirs);
325         }
326
327         allhardcount = 0;
328         if (swap_audit_file() == -1) {
329                 syslog(LOG_ERR, "Could not swap audit file\n");
330                 /*
331                  * XXX Faulty directory listing? - user should be given
332                  * XXX an opportunity to change the audit_control file
333                  * XXX switch to a reduced mode of auditing?
334                  */
335                 return (-1);
336         }
337
338         /*
339          * XXX There are synchronization problems here
340          * XXX what should we do if a trigger for the earlier limit
341          * XXX is generated here?
342          */
343         if (0 == (ret = getacmin(&minval))) {
344                 syslog(LOG_INFO, "min free = %d\n", minval);
345                 if (auditon(A_GETQCTRL, &qctrl, sizeof(qctrl)) != 0) {
346                         syslog(LOG_ERR,
347                             "could not get audit queue settings\n");
348                                 return (-1);
349                 }
350                 qctrl.aq_minfree = minval;
351                 if (auditon(A_SETQCTRL, &qctrl, sizeof(qctrl)) != 0) {
352                         syslog(LOG_ERR,
353                             "could not set audit queue settings\n");
354                         return (-1);
355                 }
356         }
357
358         return (0);
359 }
360
361 /*
362  * Close all log files, control files, and tell the audit system.
363  */
364 static int
365 close_all(void)
366 {
367         int err_ret = 0;
368         char TS[POSTFIX_LEN];
369         int aufd;
370         token_t *tok;
371         long cond;
372
373         /* Generate an audit record. */
374         if ((aufd = au_open()) == -1)
375                 syslog(LOG_ERR, "Could not create audit shutdown event.\n");
376         else {
377                 if ((tok = au_to_text("auditd::Audit shutdown")) != NULL)
378                         au_write(aufd, tok);
379                 if (au_close(aufd, 1, AUE_audit_shutdown) == -1)
380                         syslog(LOG_ERR,
381                             "Could not close audit shutdown event.\n");
382         }
383
384         /* Flush contents. */
385         cond = AUC_DISABLED;
386         err_ret = auditon(A_SETCOND, &cond, sizeof(cond));
387         if (err_ret != 0) {
388                 syslog(LOG_ERR, "Disabling audit failed! : %s\n",
389                     strerror(errno));
390                 err_ret = 1;
391         }
392         if (getTSstr(TS, POSTFIX_LEN) == 0)
393                 close_lastfile(TS);
394         if (lastfile != NULL)
395                 free(lastfile);
396
397         free_dir_q();
398         if ((remove(AUDITD_PIDFILE) == -1) || err_ret) {
399                 syslog(LOG_ERR, "Could not unregister\n");
400                 audit_warn_postsigterm();
401                 return (1);
402         }
403         endac();
404
405         if (close(triggerfd) != 0)
406                 syslog(LOG_ERR, "Error closing control file\n");
407         syslog(LOG_INFO, "Finished.\n");
408         return (0);
409 }
410
411 /*
412  * When we get a signal, we are often not at a clean point.  So, little can
413  * be done in the signal handler itself.  Instead,  we send a message to the
414  * main servicing loop to do proper handling from a non-signal-handler
415  * context.
416  */
417 static void
418 relay_signal(int signal)
419 {
420
421         if (signal == SIGHUP)
422                 sighups++;
423         if (signal == SIGTERM)
424                 sigterms++;
425 }
426
427 /*
428  * Registering the daemon.
429  */
430 static int
431 register_daemon(void)
432 {
433         FILE * pidfile;
434         int fd;
435         pid_t pid;
436
437         /* Set up the signal hander. */
438         if (signal(SIGTERM, relay_signal) == SIG_ERR) {
439                 syslog(LOG_ERR,
440                     "Could not set signal handler for SIGTERM\n");
441                 fail_exit();
442         }
443         if (signal(SIGCHLD, relay_signal) == SIG_ERR) {
444                 syslog(LOG_ERR,
445                     "Could not set signal handler for SIGCHLD\n");
446                 fail_exit();
447         }
448         if (signal(SIGHUP, relay_signal) == SIG_ERR) {
449                 syslog(LOG_ERR,
450                     "Could not set signal handler for SIGHUP\n");
451                 fail_exit();
452         }
453
454         if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) {
455                 syslog(LOG_ERR,
456                     "Could not open PID file\n");
457                 audit_warn_tmpfile();
458                 return (-1);
459         }
460
461         /* Attempt to lock the pid file; if a lock is present, exit. */
462         fd = fileno(pidfile);
463         if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
464                 syslog(LOG_ERR,
465                     "PID file is locked (is another auditd running?).\n");
466                 audit_warn_ebusy();
467                 return (-1);
468         }
469
470         pid = getpid();
471         ftruncate(fd, 0);
472         if (fprintf(pidfile, "%u\n", pid) < 0) {
473                 /* Should not start the daemon. */
474                 fail_exit();
475         }
476
477         fflush(pidfile);
478         return (0);
479 }
480
481 /*
482  * Suppress duplicate messages within a 30 second interval.   This should be
483  * enough to time to rotate log files without thrashing from soft warnings
484  * generated before the log is actually rotated.
485  */
486 #define DUPLICATE_INTERVAL      30
487 static void
488 handle_audit_trigger(int trigger)
489 {
490         static int last_trigger;
491         static time_t last_time;
492         struct dir_ent *dirent;
493         int rc;
494
495         /*
496          * Suppres duplicate messages from the kernel within the specified
497          * interval.
498          */
499         struct timeval ts;
500         struct timezone tzp;
501         time_t tt;
502
503         if (gettimeofday(&ts, &tzp) == 0) {
504                 tt = (time_t)ts.tv_sec;
505                 if ((trigger == last_trigger) &&
506                     (tt < (last_time + DUPLICATE_INTERVAL)))
507                         return;
508                 last_trigger = trigger;
509                 last_time = tt;
510         }
511
512         /*
513          * Message processing is done here.
514          */
515         dirent = TAILQ_FIRST(&dir_q);
516         switch(trigger) {
517
518         case AUDIT_TRIGGER_LOW_SPACE:
519                 syslog(LOG_INFO, "Got low space trigger\n");
520                 if (dirent && (dirent->softlim != 1)) {
521                         TAILQ_REMOVE(&dir_q, dirent, dirs);
522                                 /* Add this node to the end of the list. */
523                                 TAILQ_INSERT_TAIL(&dir_q, dirent, dirs);
524                                 audit_warn_soft(dirent->dirname);
525                                 dirent->softlim = 1;
526
527                         if (TAILQ_NEXT(TAILQ_FIRST(&dir_q), dirs) != NULL &&
528                             swap_audit_file() == -1)
529                                 syslog(LOG_ERR, "Error swapping audit file\n");
530
531                         /*
532                          * Check if the next dir has already reached its soft
533                          * limit.
534                          */
535                         dirent = TAILQ_FIRST(&dir_q);
536                         if (dirent->softlim == 1)  {
537                                 /* All dirs have reached their soft limit. */
538                                 audit_warn_allsoft();
539                         }
540                 } else {
541                         /*
542                          * Continue auditing to the current file.  Also
543                          * generate  an allsoft warning.
544                          * XXX do we want to do this ?
545                          */
546                         audit_warn_allsoft();
547                 }
548                 break;
549
550         case AUDIT_TRIGGER_NO_SPACE:
551                 syslog(LOG_INFO, "Got no space trigger\n");
552
553                 /* Delete current dir, go on to next. */
554                 TAILQ_REMOVE(&dir_q, dirent, dirs);
555                 audit_warn_hard(dirent->dirname);
556                 free(dirent->dirname);
557                 free(dirent);
558
559                 if (swap_audit_file() == -1)
560                         syslog(LOG_ERR, "Error swapping audit file\n");
561
562                 /* We are out of log directories. */
563                 audit_warn_allhard(++allhardcount);
564                 break;
565
566         case AUDIT_TRIGGER_OPEN_NEW:
567                 /*
568                  * Create a new file and swap with the one being used in
569                  * kernel
570                  */
571                 syslog(LOG_INFO, "Got open new trigger\n");
572                 if (swap_audit_file() == -1)
573                         syslog(LOG_ERR, "Error swapping audit file\n");
574                 break;
575
576         case AUDIT_TRIGGER_READ_FILE:
577                 syslog(LOG_INFO, "Got read file trigger\n");
578                 if (read_control_file() == -1)
579                         syslog(LOG_ERR, "Error in audit control file\n");
580                 if (config_audit_controls() == -1)
581                         syslog(LOG_ERR, "Error setting audit controls\n");
582                 break;
583
584         default:
585                 syslog(LOG_ERR, "Got unknown trigger %d\n", trigger);
586                 break;
587         }
588 }
589
590 static void
591 handle_sighup(void)
592 {
593
594         sighups_handled = sighups;
595         config_audit_controls();
596 }
597
598 /*
599  * Read the control file for triggers and handle appropriately.
600  */
601 static int
602 wait_for_triggers(void)
603 {
604         int num;
605         unsigned int trigger;
606
607         for (;;) {
608                 num = read(triggerfd, &trigger, sizeof(trigger));
609                 if ((num == -1) && (errno != EINTR)) {
610                         syslog(LOG_ERR, "%s: error %d\n", __FUNCTION__, errno);
611                         return (-1);
612                 }
613                 if (sigterms != sigterms_handled) {
614                         syslog(LOG_INFO, "%s: SIGTERM", __FUNCTION__);
615                         break;
616                 }
617                 if (sighups != sighups_handled) {
618                         syslog(LOG_INFO, "%s: SIGHUP", __FUNCTION__);
619                         handle_sighup();
620                 }
621                 if ((num == -1) && (errno == EINTR))
622                         continue;
623                 if (num == 0) {
624                         syslog(LOG_INFO, "%s: read EOF\n", __FUNCTION__);
625                         return (-1);
626                 }
627                 syslog(LOG_INFO, "%s: read %d\n", __FUNCTION__, trigger);
628                 if (trigger == AUDIT_TRIGGER_CLOSE_AND_DIE)
629                         break;
630                 else
631                         handle_audit_trigger(trigger);
632         }
633         return (close_all());
634 }
635
636 /*
637  * Reap our children.
638  */
639 static void
640 reap_children(void)
641 {
642         pid_t child;
643         int wstatus;
644
645         while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) {
646                 if (!wstatus)
647                         continue;
648                 syslog(LOG_INFO, "warn process [pid=%d] %s %d.\n", child,
649                     ((WIFEXITED(wstatus)) ? "exited with non-zero status" :
650                     "exited as a result of signal"),
651                     ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) :
652                     WTERMSIG(wstatus)));
653         }
654 }
655
656 /*
657  * Configure the audit controls in the kernel: the event to class mapping,
658  * kernel preselection mask, etc.
659  */
660 static int
661 config_audit_controls(void)
662 {
663         au_event_ent_t ev, *evp;
664         au_evclass_map_t evc_map;
665         au_mask_t aumask;
666         int ctr = 0;
667         char naeventstr[NA_EVENT_STR_SIZE];
668
669         /*
670          * Process the audit event file, obtaining a class mapping for each
671          * event, and send that mapping into the kernel.
672          * XXX There's a risk here that the BSM library will return NULL
673          * for an event when it can't properly map it to a class. In that
674          * case, we will not process any events beyond the one that failed,
675          * but should. We need a way to get a count of the events.
676         */
677         ev.ae_name = (char *)malloc(AU_EVENT_NAME_MAX);
678         ev.ae_desc = (char *)malloc(AU_EVENT_DESC_MAX);
679         if ((ev.ae_name == NULL) || (ev.ae_desc == NULL)) {
680                 syslog(LOG_ERR,
681                     "Memory allocation error when configuring audit controls.");
682                 return (-1);
683         }
684         evp = &ev;
685         setauevent();
686         while ((evp = getauevent_r(evp)) != NULL) {
687                 evc_map.ec_number = evp->ae_number;
688                 evc_map.ec_class = evp->ae_class;
689                 if (auditon(A_SETCLASS, &evc_map, sizeof(au_evclass_map_t))
690                     != 0)
691                         syslog(LOG_ERR,
692                                 "Failed to register class mapping for event %s",
693                                  evp->ae_name);
694                 else
695                         ctr++;
696         }
697         endauevent();
698         free(ev.ae_name);
699         free(ev.ae_desc);
700         if (ctr == 0)
701                 syslog(LOG_ERR, "No events to class mappings registered.");
702         else
703                 syslog(LOG_INFO, "Registered %d event to class mappings.",
704                     ctr);
705
706         /*
707          * Get the non-attributable event string and set the kernel mask from
708          * that.
709          */
710         if ((getacna(naeventstr, NA_EVENT_STR_SIZE) == 0) &&
711             (getauditflagsbin(naeventstr, &aumask) == 0)) {
712                 if (auditon(A_SETKMASK, &aumask, sizeof(au_mask_t)))
713                         syslog(LOG_ERR,
714                             "Failed to register non-attributable event mask.");
715                 else
716                         syslog(LOG_INFO,
717                             "Registered non-attributable event mask.");
718         } else
719                 syslog(LOG_ERR,
720                     "Failed to obtain non-attributable event mask.");
721
722         /*
723          * Set the audit policy flags based on passed in parameter values.
724          */
725         if (auditon(A_SETPOLICY, &global_flags, sizeof(global_flags)))
726                 syslog(LOG_ERR, "Failed to set audit policy.");
727
728         return (0);
729 }
730
731 static void
732 setup(void)
733 {
734         int aufd;
735         token_t *tok;
736
737         if ((triggerfd = open(AUDIT_TRIGGER_FILE, O_RDONLY, 0)) < 0) {
738                 syslog(LOG_ERR, "Error opening trigger file\n");
739                 fail_exit();
740         }
741
742         TAILQ_INIT(&dir_q);
743         if (read_control_file() == -1) {
744                 syslog(LOG_ERR, "Error reading control file\n");
745                 fail_exit();
746         }
747
748         /* Generate an audit record. */
749         if ((aufd = au_open()) == -1)
750                 syslog(LOG_ERR, "Could not create audit startup event.\n");
751         else {
752                 if ((tok = au_to_text("auditd::Audit startup")) != NULL)
753                         au_write(aufd, tok);
754                 if (au_close(aufd, 1, AUE_audit_startup) == -1)
755                         syslog(LOG_ERR,
756                             "Could not close audit startup event.\n");
757         }
758
759         if (config_audit_controls() == 0)
760                 syslog(LOG_INFO, "Audit controls init successful\n");
761         else
762                 syslog(LOG_INFO, "Audit controls init failed\n");
763 }
764
765 int
766 main(int argc, char **argv)
767 {
768         int ch;
769         int debug = 0;
770         int rc;
771
772         global_flags |= AUDIT_CNT;
773         while ((ch = getopt(argc, argv, "dhs")) != -1) {
774                 switch(ch) {
775                 case 'd':
776                         /* Debug option. */
777                         debug = 1;
778                         break;
779
780                 case 's':
781                         /* Fail-stop option. */
782                         global_flags &= ~(AUDIT_CNT);
783                         break;
784
785                 case 'h':
786                         /* Halt-stop option. */
787                         global_flags |= AUDIT_AHLT;
788                         break;
789
790                 case '?':
791                 default:
792                         (void)fprintf(stderr,
793                             "usage: auditd [-h | -s] [-d] \n");
794                         exit(1);
795                 }
796         }
797
798 #ifdef LOG_SECURITY
799         openlog("auditd", LOG_CONS | LOG_PID, LOG_SECURITY);
800 #else
801         openlog("auditd", LOG_CONS | LOG_PID, LOG_AUTH);
802 #endif
803         syslog(LOG_INFO, "starting...\n");
804
805         if (debug == 0 && daemon(0, 0) == -1) {
806                 syslog(LOG_ERR, "Failed to daemonize\n");
807                 exit(1);
808         }
809
810         if (register_daemon() == -1) {
811                 syslog(LOG_ERR, "Could not register as daemon\n");
812                 exit(1);
813         }
814
815         setup();
816
817         rc = wait_for_triggers();
818         syslog(LOG_INFO, "auditd exiting.\n");
819
820         exit(rc);
821 }