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