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_fbsd.c#4 $
30 */
31
32#include <sys/types.h>
33
34#include <config/config.h>
35
36#include <errno.h>
37#include <fcntl.h>
38#include <stdarg.h>
39#include <signal.h>
40#include <string.h>
41#include <syslog.h>
42#include <unistd.h>
43
44#include <bsm/audit.h>
45#include <bsm/audit_uevents.h>
46#include <bsm/auditd_lib.h>
47#include <bsm/libbsm.h>
48
49#include "auditd.h"
50
51/*
52 * Current auditing state (cache).
53 */
54static int	auditing_state = AUD_STATE_INIT;
55
56/*
57 * Maximum idle time before auditd terminates under launchd.
58 * If it is zero then auditd does not timeout while idle.
59 */
60static int	max_idletime = 0;
61
62static int	sigchlds, sigchlds_handled;
63static int	sighups, sighups_handled;
64static int	sigterms, sigterms_handled;
65static int	sigalrms, sigalrms_handled;
66
67static int	triggerfd = 0;
68
69/*
70 *  Open and set up system logging.
71 */
72void
73auditd_openlog(int debug, gid_t __unused gid)
74{
75	int logopts = LOG_CONS | LOG_PID;
76
77	if (debug)
78		logopts |= LOG_PERROR;
79
80#ifdef LOG_SECURITY
81	openlog("auditd", logopts, LOG_SECURITY);
82#else
83	openlog("auditd", logopts, LOG_AUTH);
84#endif
85}
86
87/*
88 * Log messages at different priority levels.
89 */
90void
91auditd_log_err(const char *fmt, ...)
92{
93	va_list ap;
94
95	va_start(ap, fmt);
96	vsyslog(LOG_ERR, fmt, ap);
97	va_end(ap);
98}
99
100void
101auditd_log_notice(const char *fmt, ...)
102{
103	va_list ap;
104
105	va_start(ap, fmt);
106	vsyslog(LOG_NOTICE, fmt, ap);
107	va_end(ap);
108}
109
110void
111auditd_log_info(const char *fmt, ...)
112{
113	va_list ap;
114
115	va_start(ap, fmt);
116	vsyslog(LOG_INFO, fmt, ap);
117	va_end(ap);
118}
119
120void
121auditd_log_debug(const char *fmt, ...)
122{
123	va_list ap;
124
125	va_start(ap, fmt);
126	vsyslog(LOG_DEBUG, fmt, ap);
127	va_end(ap);
128}
129
130/*
131 * Get the auditing state from the kernel and cache it.
132 */
133static void
134init_audit_state(void)
135{
136	int au_cond;
137
138	if (audit_get_cond(&au_cond) < 0) {
139		if (errno != ENOSYS) {
140			auditd_log_err("Audit status check failed (%s)",
141			    strerror(errno));
142		}
143		auditing_state = AUD_STATE_DISABLED;
144	} else
145		if (au_cond == AUC_NOAUDIT || au_cond == AUC_DISABLED)
146			auditing_state = AUD_STATE_DISABLED;
147		else
148			auditing_state = AUD_STATE_ENABLED;
149}
150
151/*
152 * Update the cached auditing state.
153 */
154void
155auditd_set_state(int state)
156{
157	int old_auditing_state = auditing_state;
158
159	if (state == AUD_STATE_INIT)
160		init_audit_state();
161	else
162		auditing_state = state;
163
164	if (auditing_state != old_auditing_state) {
165		if (auditing_state == AUD_STATE_ENABLED)
166			auditd_log_notice("Auditing enabled");
167		if (auditing_state == AUD_STATE_DISABLED)
168			auditd_log_notice("Auditing disabled");
169	}
170}
171
172/*
173 * Get the cached auditing state.
174 */
175int
176auditd_get_state(void)
177{
178
179	if (auditing_state == AUD_STATE_INIT)
180		init_audit_state();
181
182	return (auditing_state);
183}
184
185/*
186 * Open the trigger messaging mechanism.
187 */
188int
189auditd_open_trigger(int __unused launchd_flag)
190{
191
192	return ((triggerfd = open(AUDIT_TRIGGER_FILE, O_RDONLY, 0)));
193}
194
195/*
196 * Close the trigger messaging mechanism.
197 */
198int
199auditd_close_trigger(void)
200{
201
202	return (close(triggerfd));
203}
204
205/*
206 * The main event loop.  Wait for trigger messages or signals and handle them.
207 * It should not return unless there is a problem.
208 */
209void
210auditd_wait_for_events(void)
211{
212	int num;
213	unsigned int trigger;
214
215	for (;;) {
216		num = read(triggerfd, &trigger, sizeof(trigger));
217		if ((num == -1) && (errno != EINTR)) {
218			auditd_log_err("%s: error %d", __FUNCTION__, errno);
219			return;
220		}
221
222		/* Reset the idle time alarm, if used. */
223		if (max_idletime)
224			alarm(max_idletime);
225
226		if (sigterms != sigterms_handled) {
227			auditd_log_debug("%s: SIGTERM", __FUNCTION__);
228			auditd_terminate();
229			/* not reached */
230		}
231		if (sigalrms != sigalrms_handled) {
232			auditd_log_debug("%s: SIGALRM", __FUNCTION__);
233			auditd_terminate();
234			/* not reached */
235		}
236 		if (sigchlds != sigchlds_handled) {
237			sigchlds_handled = sigchlds;
238			auditd_reap_children();
239		}
240		if (sighups != sighups_handled) {
241			auditd_log_debug("%s: SIGHUP", __FUNCTION__);
242			sighups_handled = sighups;
243			auditd_config_controls();
244		}
245
246		if ((num == -1) && (errno == EINTR))
247			continue;
248		if (num == 0) {
249			auditd_log_err("%s: read EOF", __FUNCTION__);
250			return;
251		}
252		auditd_handle_trigger(trigger);
253	}
254}
255
256/*
257 * When we get a signal, we are often not at a clean point.  So, little can
258 * be done in the signal handler itself.  Instead,  we send a message to the
259 * main servicing loop to do proper handling from a non-signal-handler
260 * context.
261 */
262void
263auditd_relay_signal(int signal)
264{
265        if (signal == SIGHUP)
266                sighups++;
267        if (signal == SIGTERM)
268                sigterms++;
269        if (signal == SIGCHLD)
270                sigchlds++;
271	if (signal == SIGALRM)
272		sigalrms++;
273}
274
275