xref: /freebsd/contrib/openbsm/bin/auditd/auditd_fbsd.c (revision fcb560670601b2a4d87bb31d7531c8dcc37ee71b)
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  */
54 static 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  */
60 static int	max_idletime = 0;
61 
62 static int	sigchlds, sigchlds_handled;
63 static int	sighups, sighups_handled;
64 static int	sigterms, sigterms_handled;
65 static int	sigalrms, sigalrms_handled;
66 
67 static int	triggerfd = 0;
68 
69 /*
70  *  Open and set up system logging.
71  */
72 void
73 auditd_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  */
90 void
91 auditd_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 
100 void
101 auditd_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 
110 void
111 auditd_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 
120 void
121 auditd_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  */
133 static void
134 init_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  */
154 void
155 auditd_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  */
175 int
176 auditd_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  */
188 int
189 auditd_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  */
198 int
199 auditd_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  */
209 void
210 auditd_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  */
262 void
263 auditd_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