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 */
52 static 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 */
58 static int max_idletime = 0;
59
60 static int sigchlds, sigchlds_handled;
61 static int sighups, sighups_handled;
62 static int sigterms, sigterms_handled;
63 static int sigalrms, sigalrms_handled;
64
65 static int triggerfd = 0;
66
67 /*
68 * Open and set up system logging.
69 */
70 void
auditd_openlog(int debug,gid_t __unused gid)71 auditd_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 */
88 void
auditd_log_err(const char * fmt,...)89 auditd_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
98 void
auditd_log_notice(const char * fmt,...)99 auditd_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
108 void
auditd_log_info(const char * fmt,...)109 auditd_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
118 void
auditd_log_debug(const char * fmt,...)119 auditd_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 */
131 static void
init_audit_state(void)132 init_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 */
152 void
auditd_set_state(int state)153 auditd_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 */
173 int
auditd_get_state(void)174 auditd_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 */
186 int
auditd_open_trigger(int __unused launchd_flag)187 auditd_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 */
196 int
auditd_close_trigger(void)197 auditd_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 */
207 void
auditd_wait_for_events(void)208 auditd_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)
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 */
260 void
auditd_relay_signal(int signal)261 auditd_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