xref: /freebsd/contrib/openbsm/libbsm/bsm_event.c (revision b0d29bc47dba79f6f38e67eabadfb4b32ffd9390)
1 /*-
2  * Copyright (c) 2004 Apple Inc.
3  * Copyright (c) 2006 Robert N. M. Watson
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
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
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
22  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include <config/config.h>
32 
33 #include <bsm/libbsm.h>
34 
35 #include <string.h>
36 #ifdef HAVE_PTHREAD_MUTEX_LOCK
37 #include <pthread.h>
38 #endif
39 #include <stdio.h>
40 #include <stdlib.h>
41 
42 #ifndef HAVE_STRLCPY
43 #include <compat/strlcpy.h>
44 #endif
45 
46 
47 /*
48  * Parse the contents of the audit_event file to return
49  * au_event_ent entries
50  */
51 static FILE		*fp = NULL;
52 static char		 linestr[AU_LINE_MAX];
53 static const char	*eventdelim = ":";
54 
55 #ifdef HAVE_PTHREAD_MUTEX_LOCK
56 static pthread_mutex_t	mutex = PTHREAD_MUTEX_INITIALIZER;
57 #endif
58 
59 /*
60  * Parse one line from the audit_event file into the au_event_ent structure.
61  */
62 static struct au_event_ent *
63 eventfromstr(char *str, struct au_event_ent *e)
64 {
65 	char *evno, *evname, *evdesc, *evclass;
66 	struct au_mask evmask;
67 	char *last;
68 
69 	evno = strtok_r(str, eventdelim, &last);
70 	evname = strtok_r(NULL, eventdelim, &last);
71 	evdesc = strtok_r(NULL, eventdelim, &last);
72 	evclass = strtok_r(NULL, eventdelim, &last);
73 
74 	if ((evno == NULL) || (evname == NULL))
75 		return (NULL);
76 
77 	if (strlen(evname) >= AU_EVENT_NAME_MAX)
78 		return (NULL);
79 
80 	strlcpy(e->ae_name, evname, AU_EVENT_NAME_MAX);
81 	if (evdesc != NULL) {
82 		if (strlen(evdesc) >= AU_EVENT_DESC_MAX)
83 			return (NULL);
84 		strlcpy(e->ae_desc, evdesc, AU_EVENT_DESC_MAX);
85 	} else
86 		strlcpy(e->ae_desc, "", AU_EVENT_DESC_MAX);
87 
88 	e->ae_number = atoi(evno);
89 
90 	/*
91 	 * Find out the mask that corresponds to the given list of classes.
92 	 */
93 	if (evclass != NULL) {
94 		if (getauditflagsbin(evclass, &evmask) != 0)
95 			e->ae_class = 0;
96 		else
97 			e->ae_class = evmask.am_success;
98 	} else
99 		e->ae_class = 0;
100 
101 	return (e);
102 }
103 
104 /*
105  * Rewind the audit_event file.
106  */
107 static void
108 setauevent_locked(void)
109 {
110 
111 	if (fp != NULL)
112 		fseek(fp, 0, SEEK_SET);
113 }
114 
115 void
116 setauevent(void)
117 {
118 
119 #ifdef HAVE_PTHREAD_MUTEX_LOCK
120 	pthread_mutex_lock(&mutex);
121 #endif
122 	setauevent_locked();
123 #ifdef HAVE_PTHREAD_MUTEX_LOCK
124 	pthread_mutex_unlock(&mutex);
125 #endif
126 }
127 
128 /*
129  * Close the open file pointers.
130  */
131 void
132 endauevent(void)
133 {
134 
135 #ifdef HAVE_PTHREAD_MUTEX_LOCK
136 	pthread_mutex_lock(&mutex);
137 #endif
138 	if (fp != NULL) {
139 		fclose(fp);
140 		fp = NULL;
141 	}
142 #ifdef HAVE_PTHREAD_MUTEX_LOCK
143 	pthread_mutex_unlock(&mutex);
144 #endif
145 }
146 
147 /*
148  * Enumerate the au_event_ent entries.
149  */
150 static struct au_event_ent *
151 getauevent_r_locked(struct au_event_ent *e)
152 {
153 	char *nl;
154 
155 	if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL))
156 		return (NULL);
157 
158 	while (1) {
159 		if (fgets(linestr, AU_LINE_MAX, fp) == NULL)
160 			return (NULL);
161 
162 		/* Remove new lines. */
163 		if ((nl = strrchr(linestr, '\n')) != NULL)
164 			*nl = '\0';
165 
166 		/* Skip comments. */
167 		if (linestr[0] == '#')
168 			continue;
169 
170 		/* Get the next event structure. */
171 		if (eventfromstr(linestr, e) == NULL)
172 			return (NULL);
173 		break;
174 	}
175 
176 	return (e);
177 }
178 
179 struct au_event_ent *
180 getauevent_r(struct au_event_ent *e)
181 {
182 	struct au_event_ent *ep;
183 
184 #ifdef HAVE_PTHREAD_MUTEX_LOCK
185 	pthread_mutex_lock(&mutex);
186 #endif
187 	ep = getauevent_r_locked(e);
188 #ifdef HAVE_PTHREAD_MUTEX_LOCK
189 	pthread_mutex_unlock(&mutex);
190 #endif
191 	return (ep);
192 }
193 
194 struct au_event_ent *
195 getauevent(void)
196 {
197 	static char event_ent_name[AU_EVENT_NAME_MAX];
198 	static char event_ent_desc[AU_EVENT_DESC_MAX];
199 	static struct au_event_ent e;
200 
201 	bzero(&e, sizeof(e));
202 	bzero(event_ent_name, sizeof(event_ent_name));
203 	bzero(event_ent_desc, sizeof(event_ent_desc));
204 	e.ae_name = event_ent_name;
205 	e.ae_desc = event_ent_desc;
206 	return (getauevent_r(&e));
207 }
208 
209 /*
210  * Search for an audit event structure having the given event name.
211  *
212  * XXXRW: Why accept NULL name?
213  */
214 static struct au_event_ent *
215 getauevnam_r_locked(struct au_event_ent *e, const char *name)
216 {
217 	char *nl;
218 
219 	if (name == NULL)
220 		return (NULL);
221 
222 	/* Rewind to beginning of the file. */
223 	setauevent_locked();
224 
225 	if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL))
226 		return (NULL);
227 
228 	while (fgets(linestr, AU_LINE_MAX, fp) != NULL) {
229 		/* Remove new lines. */
230 		if ((nl = strrchr(linestr, '\n')) != NULL)
231 			*nl = '\0';
232 
233 		if (eventfromstr(linestr, e) != NULL) {
234 			if (strcmp(name, e->ae_name) == 0)
235 				return (e);
236 		}
237 	}
238 
239 	return (NULL);
240 }
241 
242 struct au_event_ent *
243 getauevnam_r(struct au_event_ent *e, const char *name)
244 {
245 	struct au_event_ent *ep;
246 
247 #ifdef HAVE_PTHREAD_MUTEX_LOCK
248 	pthread_mutex_lock(&mutex);
249 #endif
250 	ep = getauevnam_r_locked(e, name);
251 #ifdef HAVE_PTHREAD_MUTEX_LOCK
252 	pthread_mutex_unlock(&mutex);
253 #endif
254 	return (ep);
255 }
256 
257 struct au_event_ent *
258 getauevnam(const char *name)
259 {
260 	static char event_ent_name[AU_EVENT_NAME_MAX];
261 	static char event_ent_desc[AU_EVENT_DESC_MAX];
262 	static struct au_event_ent e;
263 
264 	bzero(&e, sizeof(e));
265 	bzero(event_ent_name, sizeof(event_ent_name));
266 	bzero(event_ent_desc, sizeof(event_ent_desc));
267 	e.ae_name = event_ent_name;
268 	e.ae_desc = event_ent_desc;
269 	return (getauevnam_r(&e, name));
270 }
271 
272 /*
273  * Search for an audit event structure having the given event number.
274  */
275 static struct au_event_ent *
276 getauevnum_r_locked(struct au_event_ent *e, au_event_t event_number)
277 {
278 	char *nl;
279 
280 	/* Rewind to beginning of the file. */
281 	setauevent_locked();
282 
283 	if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL))
284 		return (NULL);
285 
286 	while (fgets(linestr, AU_LINE_MAX, fp) != NULL) {
287 		/* Remove new lines. */
288 		if ((nl = strrchr(linestr, '\n')) != NULL)
289 			*nl = '\0';
290 
291 		if (eventfromstr(linestr, e) != NULL) {
292 			if (event_number == e->ae_number)
293 				return (e);
294 		}
295 	}
296 
297 	return (NULL);
298 }
299 
300 struct au_event_ent *
301 getauevnum_r(struct au_event_ent *e, au_event_t event_number)
302 {
303 	struct au_event_ent *ep;
304 
305 #ifdef HAVE_PTHREAD_MUTEX_LOCK
306 	pthread_mutex_lock(&mutex);
307 #endif
308 	ep = getauevnum_r_locked(e, event_number);
309 #ifdef HAVE_PTHREAD_MUTEX_LOCK
310 	pthread_mutex_unlock(&mutex);
311 #endif
312 	return (ep);
313 }
314 
315 struct au_event_ent *
316 getauevnum(au_event_t event_number)
317 {
318 	static char event_ent_name[AU_EVENT_NAME_MAX];
319 	static char event_ent_desc[AU_EVENT_DESC_MAX];
320 	static struct au_event_ent e;
321 
322 	bzero(&e, sizeof(e));
323 	bzero(event_ent_name, sizeof(event_ent_name));
324 	bzero(event_ent_desc, sizeof(event_ent_desc));
325 	e.ae_name = event_ent_name;
326 	e.ae_desc = event_ent_desc;
327 	return (getauevnum_r(&e, event_number));
328 }
329 
330 /*
331  * Search for an audit_event entry with a given event_name and returns the
332  * corresponding event number.
333  */
334 au_event_t *
335 getauevnonam_r(au_event_t *ev, const char *event_name)
336 {
337 	static char event_ent_name[AU_EVENT_NAME_MAX];
338 	static char event_ent_desc[AU_EVENT_DESC_MAX];
339 	static struct au_event_ent e, *ep;
340 
341 	bzero(event_ent_name, sizeof(event_ent_name));
342 	bzero(event_ent_desc, sizeof(event_ent_desc));
343 	bzero(&e, sizeof(e));
344 	e.ae_name = event_ent_name;
345 	e.ae_desc = event_ent_desc;
346 
347 	ep = getauevnam_r(&e, event_name);
348 	if (ep == NULL)
349 		return (NULL);
350 
351 	*ev = e.ae_number;
352 	return (ev);
353 }
354 
355 au_event_t *
356 getauevnonam(const char *event_name)
357 {
358 	static au_event_t event;
359 
360 	return (getauevnonam_r(&event, event_name));
361 }
362