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