bsm_event.c revision 293161
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 */
51static FILE		*fp = NULL;
52static char		 linestr[AU_LINE_MAX];
53static const char	*eventdelim = ":";
54
55#ifdef HAVE_PTHREAD_MUTEX_LOCK
56static 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 */
62static struct au_event_ent *
63eventfromstr(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 */
107static void
108setauevent_locked(void)
109{
110
111	if (fp != NULL)
112		fseek(fp, 0, SEEK_SET);
113}
114
115void
116setauevent(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 */
131void
132endauevent(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 */
150static struct au_event_ent *
151getauevent_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
179struct au_event_ent *
180getauevent_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
194struct au_event_ent *
195getauevent(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 */
214static struct au_event_ent *
215getauevnam_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
242struct au_event_ent *
243getauevnam_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
257struct au_event_ent *
258getauevnam(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 */
275static struct au_event_ent *
276getauevnum_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
300struct au_event_ent *
301getauevnum_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
315struct au_event_ent *
316getauevnum(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 */
334au_event_t *
335getauevnonam_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
355au_event_t *
356getauevnonam(const char *event_name)
357{
358	static au_event_t event;
359
360	return (getauevnonam_r(&event, event_name));
361}
362