xref: /freebsd/contrib/openbsm/libbsm/bsm_event.c (revision b626f5a73a48f44a31a200291b141e1da408a2ff)
152267f74SRobert Watson /*-
252267f74SRobert Watson  * Copyright (c) 2004 Apple Inc.
3ca0716f5SRobert Watson  * Copyright (c) 2006 Robert N. M. Watson
4ca0716f5SRobert Watson  * All rights reserved.
5ca0716f5SRobert Watson  *
6ca0716f5SRobert Watson  * Redistribution and use in source and binary forms, with or without
7ca0716f5SRobert Watson  * modification, are permitted provided that the following conditions
8ca0716f5SRobert Watson  * are met:
9ca0716f5SRobert Watson  * 1.  Redistributions of source code must retain the above copyright
10ca0716f5SRobert Watson  *     notice, this list of conditions and the following disclaimer.
11ca0716f5SRobert Watson  * 2.  Redistributions in binary form must reproduce the above copyright
12ca0716f5SRobert Watson  *     notice, this list of conditions and the following disclaimer in the
13ca0716f5SRobert Watson  *     documentation and/or other materials provided with the distribution.
1452267f74SRobert Watson  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
15ca0716f5SRobert Watson  *     its contributors may be used to endorse or promote products derived
16ca0716f5SRobert Watson  *     from this software without specific prior written permission.
17ca0716f5SRobert Watson  *
18ca0716f5SRobert Watson  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
19ca0716f5SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20ca0716f5SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21ca0716f5SRobert Watson  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
22ca0716f5SRobert Watson  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23ca0716f5SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24ca0716f5SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25ca0716f5SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26ca0716f5SRobert Watson  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27ca0716f5SRobert Watson  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28ca0716f5SRobert Watson  * POSSIBILITY OF SUCH DAMAGE.
29ca0716f5SRobert Watson  */
30ca0716f5SRobert Watson 
3152267f74SRobert Watson #include <config/config.h>
3252267f74SRobert Watson 
33ca0716f5SRobert Watson #include <bsm/libbsm.h>
34ca0716f5SRobert Watson 
35ca0716f5SRobert Watson #include <string.h>
367a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
37ca0716f5SRobert Watson #include <pthread.h>
387a0a89d2SRobert Watson #endif
39ca0716f5SRobert Watson #include <stdio.h>
40ca0716f5SRobert Watson #include <stdlib.h>
41ca0716f5SRobert Watson 
4252267f74SRobert Watson #ifndef HAVE_STRLCPY
4352267f74SRobert Watson #include <compat/strlcpy.h>
4452267f74SRobert Watson #endif
4552267f74SRobert Watson 
4652267f74SRobert Watson 
47ca0716f5SRobert Watson /*
48ca0716f5SRobert Watson  * Parse the contents of the audit_event file to return
49ca0716f5SRobert Watson  * au_event_ent entries
50ca0716f5SRobert Watson  */
51ca0716f5SRobert Watson static FILE		*fp = NULL;
52ca0716f5SRobert Watson static char		 linestr[AU_LINE_MAX];
53ca0716f5SRobert Watson static const char	*eventdelim = ":";
54ca0716f5SRobert Watson 
557a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
56ca0716f5SRobert Watson static pthread_mutex_t	mutex = PTHREAD_MUTEX_INITIALIZER;
577a0a89d2SRobert Watson #endif
58ca0716f5SRobert Watson 
59ca0716f5SRobert Watson /*
60ca0716f5SRobert Watson  * Parse one line from the audit_event file into the au_event_ent structure.
61ca0716f5SRobert Watson  */
62ca0716f5SRobert Watson static struct au_event_ent *
eventfromstr(char * str,struct au_event_ent * e)63ca0716f5SRobert Watson eventfromstr(char *str, struct au_event_ent *e)
64ca0716f5SRobert Watson {
65ca0716f5SRobert Watson 	char *evno, *evname, *evdesc, *evclass;
66ca0716f5SRobert Watson 	struct au_mask evmask;
67ca0716f5SRobert Watson 	char *last;
68ca0716f5SRobert Watson 
69ca0716f5SRobert Watson 	evno = strtok_r(str, eventdelim, &last);
70ca0716f5SRobert Watson 	evname = strtok_r(NULL, eventdelim, &last);
71ca0716f5SRobert Watson 	evdesc = strtok_r(NULL, eventdelim, &last);
72ca0716f5SRobert Watson 	evclass = strtok_r(NULL, eventdelim, &last);
73ca0716f5SRobert Watson 
7422ccb20dSRobert Watson 	if ((evno == NULL) || (evname == NULL))
75ca0716f5SRobert Watson 		return (NULL);
76ca0716f5SRobert Watson 
77ca0716f5SRobert Watson 	if (strlen(evname) >= AU_EVENT_NAME_MAX)
78ca0716f5SRobert Watson 		return (NULL);
79ca0716f5SRobert Watson 
8052267f74SRobert Watson 	strlcpy(e->ae_name, evname, AU_EVENT_NAME_MAX);
8122ccb20dSRobert Watson 	if (evdesc != NULL) {
82ca0716f5SRobert Watson 		if (strlen(evdesc) >= AU_EVENT_DESC_MAX)
83ca0716f5SRobert Watson 			return (NULL);
8452267f74SRobert Watson 		strlcpy(e->ae_desc, evdesc, AU_EVENT_DESC_MAX);
8522ccb20dSRobert Watson 	} else
8652267f74SRobert Watson 		strlcpy(e->ae_desc, "", AU_EVENT_DESC_MAX);
87ca0716f5SRobert Watson 
88ca0716f5SRobert Watson 	e->ae_number = atoi(evno);
89ca0716f5SRobert Watson 
90ca0716f5SRobert Watson 	/*
91ca0716f5SRobert Watson 	 * Find out the mask that corresponds to the given list of classes.
92ca0716f5SRobert Watson 	 */
9322ccb20dSRobert Watson 	if (evclass != NULL) {
94ca0716f5SRobert Watson 		if (getauditflagsbin(evclass, &evmask) != 0)
95eb336521SRobert Watson 			e->ae_class = 0;
96ca0716f5SRobert Watson 		else
97ca0716f5SRobert Watson 			e->ae_class = evmask.am_success;
9822ccb20dSRobert Watson 	} else
99eb336521SRobert Watson 		e->ae_class = 0;
100ca0716f5SRobert Watson 
101ca0716f5SRobert Watson 	return (e);
102ca0716f5SRobert Watson }
103ca0716f5SRobert Watson 
104ca0716f5SRobert Watson /*
105ca0716f5SRobert Watson  * Rewind the audit_event file.
106ca0716f5SRobert Watson  */
107ca0716f5SRobert Watson static void
setauevent_locked(void)108ca0716f5SRobert Watson setauevent_locked(void)
109ca0716f5SRobert Watson {
110ca0716f5SRobert Watson 
111ca0716f5SRobert Watson 	if (fp != NULL)
112ca0716f5SRobert Watson 		fseek(fp, 0, SEEK_SET);
113ca0716f5SRobert Watson }
114ca0716f5SRobert Watson 
115ca0716f5SRobert Watson void
setauevent(void)116ca0716f5SRobert Watson setauevent(void)
117ca0716f5SRobert Watson {
118ca0716f5SRobert Watson 
1197a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
120ca0716f5SRobert Watson 	pthread_mutex_lock(&mutex);
1217a0a89d2SRobert Watson #endif
122ca0716f5SRobert Watson 	setauevent_locked();
1237a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
124ca0716f5SRobert Watson 	pthread_mutex_unlock(&mutex);
1257a0a89d2SRobert Watson #endif
126ca0716f5SRobert Watson }
127ca0716f5SRobert Watson 
128ca0716f5SRobert Watson /*
129ca0716f5SRobert Watson  * Close the open file pointers.
130ca0716f5SRobert Watson  */
131ca0716f5SRobert Watson void
endauevent(void)132ca0716f5SRobert Watson endauevent(void)
133ca0716f5SRobert Watson {
134ca0716f5SRobert Watson 
1357a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
136ca0716f5SRobert Watson 	pthread_mutex_lock(&mutex);
1377a0a89d2SRobert Watson #endif
138ca0716f5SRobert Watson 	if (fp != NULL) {
139ca0716f5SRobert Watson 		fclose(fp);
140ca0716f5SRobert Watson 		fp = NULL;
141ca0716f5SRobert Watson 	}
1427a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
143ca0716f5SRobert Watson 	pthread_mutex_unlock(&mutex);
1447a0a89d2SRobert Watson #endif
145ca0716f5SRobert Watson }
146ca0716f5SRobert Watson 
147ca0716f5SRobert Watson /*
148ca0716f5SRobert Watson  * Enumerate the au_event_ent entries.
149ca0716f5SRobert Watson  */
150ca0716f5SRobert Watson static struct au_event_ent *
getauevent_r_locked(struct au_event_ent * e)151ca0716f5SRobert Watson getauevent_r_locked(struct au_event_ent *e)
152ca0716f5SRobert Watson {
153ca0716f5SRobert Watson 	char *nl;
154ca0716f5SRobert Watson 
155ca0716f5SRobert Watson 	if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL))
156ca0716f5SRobert Watson 		return (NULL);
157ca0716f5SRobert Watson 
158ca0716f5SRobert Watson 	while (1) {
159ca0716f5SRobert Watson 		if (fgets(linestr, AU_LINE_MAX, fp) == NULL)
160ca0716f5SRobert Watson 			return (NULL);
161ca0716f5SRobert Watson 
162ca0716f5SRobert Watson 		/* Remove new lines. */
163ca0716f5SRobert Watson 		if ((nl = strrchr(linestr, '\n')) != NULL)
164ca0716f5SRobert Watson 			*nl = '\0';
165ca0716f5SRobert Watson 
166ca0716f5SRobert Watson 		/* Skip comments. */
167ca0716f5SRobert Watson 		if (linestr[0] == '#')
168ca0716f5SRobert Watson 			continue;
169ca0716f5SRobert Watson 
170ca0716f5SRobert Watson 		/* Get the next event structure. */
171ca0716f5SRobert Watson 		if (eventfromstr(linestr, e) == NULL)
172ca0716f5SRobert Watson 			return (NULL);
173ca0716f5SRobert Watson 		break;
174ca0716f5SRobert Watson 	}
175ca0716f5SRobert Watson 
176ca0716f5SRobert Watson 	return (e);
177ca0716f5SRobert Watson }
178ca0716f5SRobert Watson 
179ca0716f5SRobert Watson struct au_event_ent *
getauevent_r(struct au_event_ent * e)180ca0716f5SRobert Watson getauevent_r(struct au_event_ent *e)
181ca0716f5SRobert Watson {
182ca0716f5SRobert Watson 	struct au_event_ent *ep;
183ca0716f5SRobert Watson 
1847a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
185ca0716f5SRobert Watson 	pthread_mutex_lock(&mutex);
1867a0a89d2SRobert Watson #endif
187ca0716f5SRobert Watson 	ep = getauevent_r_locked(e);
1887a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
189ca0716f5SRobert Watson 	pthread_mutex_unlock(&mutex);
1907a0a89d2SRobert Watson #endif
191ca0716f5SRobert Watson 	return (ep);
192ca0716f5SRobert Watson }
193ca0716f5SRobert Watson 
194ca0716f5SRobert Watson struct au_event_ent *
getauevent(void)195ca0716f5SRobert Watson getauevent(void)
196ca0716f5SRobert Watson {
197ca0716f5SRobert Watson 	static char event_ent_name[AU_EVENT_NAME_MAX];
198ca0716f5SRobert Watson 	static char event_ent_desc[AU_EVENT_DESC_MAX];
199ca0716f5SRobert Watson 	static struct au_event_ent e;
200ca0716f5SRobert Watson 
201ca0716f5SRobert Watson 	bzero(&e, sizeof(e));
202ca0716f5SRobert Watson 	bzero(event_ent_name, sizeof(event_ent_name));
203ca0716f5SRobert Watson 	bzero(event_ent_desc, sizeof(event_ent_desc));
204ca0716f5SRobert Watson 	e.ae_name = event_ent_name;
205ca0716f5SRobert Watson 	e.ae_desc = event_ent_desc;
206ca0716f5SRobert Watson 	return (getauevent_r(&e));
207ca0716f5SRobert Watson }
208ca0716f5SRobert Watson 
209ca0716f5SRobert Watson /*
210ca0716f5SRobert Watson  * Search for an audit event structure having the given event name.
211ca0716f5SRobert Watson  *
212ca0716f5SRobert Watson  * XXXRW: Why accept NULL name?
213ca0716f5SRobert Watson  */
214ca0716f5SRobert Watson static struct au_event_ent *
getauevnam_r_locked(struct au_event_ent * e,const char * name)215ca0716f5SRobert Watson getauevnam_r_locked(struct au_event_ent *e, const char *name)
216ca0716f5SRobert Watson {
217ca0716f5SRobert Watson 	char *nl;
218ca0716f5SRobert Watson 
219ca0716f5SRobert Watson 	if (name == NULL)
220ca0716f5SRobert Watson 		return (NULL);
221ca0716f5SRobert Watson 
222ca0716f5SRobert Watson 	/* Rewind to beginning of the file. */
223ca0716f5SRobert Watson 	setauevent_locked();
224ca0716f5SRobert Watson 
225ca0716f5SRobert Watson 	if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL))
226ca0716f5SRobert Watson 		return (NULL);
227ca0716f5SRobert Watson 
228ca0716f5SRobert Watson 	while (fgets(linestr, AU_LINE_MAX, fp) != NULL) {
229ca0716f5SRobert Watson 		/* Remove new lines. */
230ca0716f5SRobert Watson 		if ((nl = strrchr(linestr, '\n')) != NULL)
231ca0716f5SRobert Watson 			*nl = '\0';
232ca0716f5SRobert Watson 
233ca0716f5SRobert Watson 		if (eventfromstr(linestr, e) != NULL) {
234ca0716f5SRobert Watson 			if (strcmp(name, e->ae_name) == 0)
235ca0716f5SRobert Watson 				return (e);
236ca0716f5SRobert Watson 		}
237ca0716f5SRobert Watson 	}
238ca0716f5SRobert Watson 
239ca0716f5SRobert Watson 	return (NULL);
240ca0716f5SRobert Watson }
241ca0716f5SRobert Watson 
242ca0716f5SRobert Watson struct au_event_ent *
getauevnam_r(struct au_event_ent * e,const char * name)243ca0716f5SRobert Watson getauevnam_r(struct au_event_ent *e, const char *name)
244ca0716f5SRobert Watson {
245ca0716f5SRobert Watson 	struct au_event_ent *ep;
246ca0716f5SRobert Watson 
2477a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
248ca0716f5SRobert Watson 	pthread_mutex_lock(&mutex);
2497a0a89d2SRobert Watson #endif
250ca0716f5SRobert Watson 	ep = getauevnam_r_locked(e, name);
2517a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
252ca0716f5SRobert Watson 	pthread_mutex_unlock(&mutex);
2537a0a89d2SRobert Watson #endif
254ca0716f5SRobert Watson 	return (ep);
255ca0716f5SRobert Watson }
256ca0716f5SRobert Watson 
257ca0716f5SRobert Watson struct au_event_ent *
getauevnam(const char * name)258ca0716f5SRobert Watson getauevnam(const char *name)
259ca0716f5SRobert Watson {
260ca0716f5SRobert Watson 	static char event_ent_name[AU_EVENT_NAME_MAX];
261ca0716f5SRobert Watson 	static char event_ent_desc[AU_EVENT_DESC_MAX];
262ca0716f5SRobert Watson 	static struct au_event_ent e;
263ca0716f5SRobert Watson 
264ca0716f5SRobert Watson 	bzero(&e, sizeof(e));
265ca0716f5SRobert Watson 	bzero(event_ent_name, sizeof(event_ent_name));
266ca0716f5SRobert Watson 	bzero(event_ent_desc, sizeof(event_ent_desc));
267ca0716f5SRobert Watson 	e.ae_name = event_ent_name;
268ca0716f5SRobert Watson 	e.ae_desc = event_ent_desc;
269ca0716f5SRobert Watson 	return (getauevnam_r(&e, name));
270ca0716f5SRobert Watson }
271ca0716f5SRobert Watson 
272ca0716f5SRobert Watson /*
273ca0716f5SRobert Watson  * Search for an audit event structure having the given event number.
274ca0716f5SRobert Watson  */
275ca0716f5SRobert Watson static struct au_event_ent *
getauevnum_r_locked(struct au_event_ent * e,au_event_t event_number)276ca0716f5SRobert Watson getauevnum_r_locked(struct au_event_ent *e, au_event_t event_number)
277ca0716f5SRobert Watson {
278ca0716f5SRobert Watson 	char *nl;
279ca0716f5SRobert Watson 
280ca0716f5SRobert Watson 	/* Rewind to beginning of the file. */
281ca0716f5SRobert Watson 	setauevent_locked();
282ca0716f5SRobert Watson 
283ca0716f5SRobert Watson 	if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL))
284ca0716f5SRobert Watson 		return (NULL);
285ca0716f5SRobert Watson 
286ca0716f5SRobert Watson 	while (fgets(linestr, AU_LINE_MAX, fp) != NULL) {
287ca0716f5SRobert Watson 		/* Remove new lines. */
288ca0716f5SRobert Watson 		if ((nl = strrchr(linestr, '\n')) != NULL)
289ca0716f5SRobert Watson 			*nl = '\0';
290ca0716f5SRobert Watson 
291ca0716f5SRobert Watson 		if (eventfromstr(linestr, e) != NULL) {
292ca0716f5SRobert Watson 			if (event_number == e->ae_number)
293ca0716f5SRobert Watson 				return (e);
294ca0716f5SRobert Watson 		}
295ca0716f5SRobert Watson 	}
296ca0716f5SRobert Watson 
297ca0716f5SRobert Watson 	return (NULL);
298ca0716f5SRobert Watson }
299ca0716f5SRobert Watson 
300ca0716f5SRobert Watson struct au_event_ent *
getauevnum_r(struct au_event_ent * e,au_event_t event_number)301ca0716f5SRobert Watson getauevnum_r(struct au_event_ent *e, au_event_t event_number)
302ca0716f5SRobert Watson {
303ca0716f5SRobert Watson 	struct au_event_ent *ep;
304ca0716f5SRobert Watson 
3057a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
306ca0716f5SRobert Watson 	pthread_mutex_lock(&mutex);
3077a0a89d2SRobert Watson #endif
308ca0716f5SRobert Watson 	ep = getauevnum_r_locked(e, event_number);
3097a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
310ca0716f5SRobert Watson 	pthread_mutex_unlock(&mutex);
3117a0a89d2SRobert Watson #endif
312ca0716f5SRobert Watson 	return (ep);
313ca0716f5SRobert Watson }
314ca0716f5SRobert Watson 
315ca0716f5SRobert Watson struct au_event_ent *
getauevnum(au_event_t event_number)316ca0716f5SRobert Watson getauevnum(au_event_t event_number)
317ca0716f5SRobert Watson {
318ca0716f5SRobert Watson 	static char event_ent_name[AU_EVENT_NAME_MAX];
319ca0716f5SRobert Watson 	static char event_ent_desc[AU_EVENT_DESC_MAX];
320ca0716f5SRobert Watson 	static struct au_event_ent e;
321ca0716f5SRobert Watson 
322ca0716f5SRobert Watson 	bzero(&e, sizeof(e));
323ca0716f5SRobert Watson 	bzero(event_ent_name, sizeof(event_ent_name));
324ca0716f5SRobert Watson 	bzero(event_ent_desc, sizeof(event_ent_desc));
325ca0716f5SRobert Watson 	e.ae_name = event_ent_name;
326ca0716f5SRobert Watson 	e.ae_desc = event_ent_desc;
327ca0716f5SRobert Watson 	return (getauevnum_r(&e, event_number));
328ca0716f5SRobert Watson }
329ca0716f5SRobert Watson 
330ca0716f5SRobert Watson /*
331ca0716f5SRobert Watson  * Search for an audit_event entry with a given event_name and returns the
332ca0716f5SRobert Watson  * corresponding event number.
333ca0716f5SRobert Watson  */
334ca0716f5SRobert Watson au_event_t *
getauevnonam_r(au_event_t * ev,const char * event_name)335ca0716f5SRobert Watson getauevnonam_r(au_event_t *ev, const char *event_name)
336ca0716f5SRobert Watson {
337ca0716f5SRobert Watson 	static char event_ent_name[AU_EVENT_NAME_MAX];
338ca0716f5SRobert Watson 	static char event_ent_desc[AU_EVENT_DESC_MAX];
339ca0716f5SRobert Watson 	static struct au_event_ent e, *ep;
340ca0716f5SRobert Watson 
341ca0716f5SRobert Watson 	bzero(event_ent_name, sizeof(event_ent_name));
342ca0716f5SRobert Watson 	bzero(event_ent_desc, sizeof(event_ent_desc));
343ca0716f5SRobert Watson 	bzero(&e, sizeof(e));
344ca0716f5SRobert Watson 	e.ae_name = event_ent_name;
345ca0716f5SRobert Watson 	e.ae_desc = event_ent_desc;
346ca0716f5SRobert Watson 
347ca0716f5SRobert Watson 	ep = getauevnam_r(&e, event_name);
348ca0716f5SRobert Watson 	if (ep == NULL)
349ca0716f5SRobert Watson 		return (NULL);
350ca0716f5SRobert Watson 
351ca0716f5SRobert Watson 	*ev = e.ae_number;
352ca0716f5SRobert Watson 	return (ev);
353ca0716f5SRobert Watson }
354ca0716f5SRobert Watson 
355ca0716f5SRobert Watson au_event_t *
getauevnonam(const char * event_name)356ca0716f5SRobert Watson getauevnonam(const char *event_name)
357ca0716f5SRobert Watson {
358ca0716f5SRobert Watson 	static au_event_t event;
359ca0716f5SRobert Watson 
360ca0716f5SRobert Watson 	return (getauevnonam_r(&event, event_name));
361ca0716f5SRobert Watson }
362