xref: /freebsd/contrib/openbsm/bin/auditd/auditd_fbsd.c (revision fed1ca4b719c56c930f2259d80663cd34be812bb)
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
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
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
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
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
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
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
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
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
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
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
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) && (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  */
260 void
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