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