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