bsm_event.c revision 155131
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 */
44static FILE		*fp = NULL;
45static char		 linestr[AU_LINE_MAX];
46static const char	*eventdelim = ":";
47
48static 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 */
53static struct au_event_ent *
54eventfromstr(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 */
93static void
94setauevent_locked(void)
95{
96
97	if (fp != NULL)
98		fseek(fp, 0, SEEK_SET);
99}
100
101void
102setauevent(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 */
113void
114endauevent(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 */
128static struct au_event_ent *
129getauevent_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
157struct au_event_ent *
158getauevent_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
168struct au_event_ent *
169getauevent(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 */
188static struct au_event_ent *
189getauevnam_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
216struct au_event_ent *
217getauevnam_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
227struct au_event_ent *
228getauevnam(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 */
245static struct au_event_ent *
246getauevnum_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
270struct au_event_ent *
271getauevnum_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
281struct au_event_ent *
282getauevnum(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 */
300au_event_t *
301getauevnonam_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
321au_event_t *
322getauevnonam(const char *event_name)
323{
324	static au_event_t event;
325
326	return (getauevnonam_r(&event, event_name));
327}
328