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