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