bsm_event.c revision 185573
162587Sitojun/*-
278064Sume * Copyright (c) 2004 Apple Inc.
362587Sitojun * Copyright (c) 2006 Robert N. M. Watson
453541Sshin * All rights reserved.
553541Sshin *
653541Sshin * Redistribution and use in source and binary forms, with or without
753541Sshin * modification, are permitted provided that the following conditions
853541Sshin * are met:
953541Sshin * 1.  Redistributions of source code must retain the above copyright
1053541Sshin *     notice, this list of conditions and the following disclaimer.
1153541Sshin * 2.  Redistributions in binary form must reproduce the above copyright
1253541Sshin *     notice, this list of conditions and the following disclaimer in the
1353541Sshin *     documentation and/or other materials provided with the distribution.
1453541Sshin * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
1553541Sshin *     its contributors may be used to endorse or promote products derived
1653541Sshin *     from this software without specific prior written permission.
1753541Sshin *
1853541Sshin * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
1953541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2053541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2153541Sshin * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
2253541Sshin * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2353541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2453541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2553541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2653541Sshin * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
2753541Sshin * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2853541Sshin * POSSIBILITY OF SUCH DAMAGE.
2953541Sshin *
3053541Sshin * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_event.c#16 $
3153541Sshin */
3253541Sshin
3353541Sshin#include <config/config.h>
3453541Sshin
3553541Sshin#include <bsm/libbsm.h>
3653541Sshin
3753541Sshin#include <string.h>
3853541Sshin#include <pthread.h>
3978064Sume#include <stdio.h>
4053541Sshin#include <stdlib.h>
4153541Sshin
4253541Sshin#ifndef HAVE_STRLCPY
4353541Sshin#include <compat/strlcpy.h>
4453541Sshin#endif
4553541Sshin
4653541Sshin
4753541Sshin/*
4853541Sshin * Parse the contents of the audit_event file to return
4953541Sshin * au_event_ent entries
5081127Sume */
5153541Sshinstatic FILE		*fp = NULL;
5262587Sitojunstatic char		 linestr[AU_LINE_MAX];
5353541Sshinstatic const char	*eventdelim = ":";
5478064Sume
5581127Sumestatic pthread_mutex_t	mutex = PTHREAD_MUTEX_INITIALIZER;
5653541Sshin
5753541Sshin/*
5853541Sshin * Parse one line from the audit_event file into the au_event_ent structure.
5962587Sitojun */
6053541Sshinstatic struct au_event_ent *
6153541Sshineventfromstr(char *str, struct au_event_ent *e)
6253541Sshin{
6362587Sitojun	char *evno, *evname, *evdesc, *evclass;
6453541Sshin	struct au_mask evmask;
6578064Sume	char *last;
6678064Sume
6778064Sume	evno = strtok_r(str, eventdelim, &last);
6878064Sume	evname = strtok_r(NULL, eventdelim, &last);
6978064Sume	evdesc = strtok_r(NULL, eventdelim, &last);
7078064Sume	evclass = strtok_r(NULL, eventdelim, &last);
7178064Sume
7278064Sume	if ((evno == NULL) || (evname == NULL))
7381127Sume		return (NULL);
7481127Sume
7581127Sume	if (strlen(evname) >= AU_EVENT_NAME_MAX)
7662587Sitojun		return (NULL);
7778064Sume
7862587Sitojun	strlcpy(e->ae_name, evname, AU_EVENT_NAME_MAX);
7962587Sitojun	if (evdesc != NULL) {
8062587Sitojun		if (strlen(evdesc) >= AU_EVENT_DESC_MAX)
8162587Sitojun			return (NULL);
8253541Sshin		strlcpy(e->ae_desc, evdesc, AU_EVENT_DESC_MAX);
8362587Sitojun	} else
8462587Sitojun		strlcpy(e->ae_desc, "", AU_EVENT_DESC_MAX);
8562587Sitojun
8662587Sitojun	e->ae_number = atoi(evno);
8762587Sitojun
8862587Sitojun	/*
8962587Sitojun	 * Find out the mask that corresponds to the given list of classes.
9053541Sshin	 */
9162587Sitojun	if (evclass != NULL) {
9262587Sitojun		if (getauditflagsbin(evclass, &evmask) != 0)
9353541Sshin			e->ae_class = 0;
9453541Sshin		else
9553541Sshin			e->ae_class = evmask.am_success;
9653541Sshin	} else
9762587Sitojun		e->ae_class = 0;
9862587Sitojun
9962587Sitojun	return (e);
10053541Sshin}
10153541Sshin
10262587Sitojun/*
10362587Sitojun * Rewind the audit_event file.
10495023Ssuz */
10553541Sshinstatic void
10653541Sshinsetauevent_locked(void)
10753541Sshin{
10853541Sshin
10953541Sshin	if (fp != NULL)
11062587Sitojun		fseek(fp, 0, SEEK_SET);
11162587Sitojun}
11262587Sitojun
11362587Sitojunvoid
11462587Sitojunsetauevent(void)
11562587Sitojun{
11662587Sitojun
11753541Sshin	pthread_mutex_lock(&mutex);
11853541Sshin	setauevent_locked();
11953541Sshin	pthread_mutex_unlock(&mutex);
12053541Sshin}
12153541Sshin
12262587Sitojun/*
12362587Sitojun * Close the open file pointers.
12453541Sshin */
12553541Sshinvoid
12662587Sitojunendauevent(void)
12762587Sitojun{
12853541Sshin
12962587Sitojun	pthread_mutex_lock(&mutex);
13062587Sitojun	if (fp != NULL) {
13162587Sitojun		fclose(fp);
13253541Sshin		fp = NULL;
13353541Sshin	}
13453541Sshin	pthread_mutex_unlock(&mutex);
13578064Sume}
13678064Sume
13778064Sume/*
13878064Sume * Enumerate the au_event_ent entries.
13978064Sume */
14078064Sumestatic struct au_event_ent *
14178064Sumegetauevent_r_locked(struct au_event_ent *e)
14278064Sume{
14378064Sume	char *nl;
14478064Sume
14578064Sume	if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL))
14678064Sume		return (NULL);
14778064Sume
14878064Sume	while (1) {
14978064Sume		if (fgets(linestr, AU_LINE_MAX, fp) == NULL)
15078064Sume			return (NULL);
15178064Sume
15278064Sume		/* Remove new lines. */
15378064Sume		if ((nl = strrchr(linestr, '\n')) != NULL)
15478064Sume			*nl = '\0';
155120913Sume
15678064Sume		/* Skip comments. */
15778064Sume		if (linestr[0] == '#')
15878064Sume			continue;
15978064Sume
16078064Sume		/* Get the next event structure. */
16178064Sume		if (eventfromstr(linestr, e) == NULL)
16278064Sume			return (NULL);
16378064Sume		break;
16478064Sume	}
16578064Sume
16678064Sume	return (e);
16778064Sume}
16878064Sume
16978064Sumestruct au_event_ent *
17078064Sumegetauevent_r(struct au_event_ent *e)
17178064Sume{
17278064Sume	struct au_event_ent *ep;
17378064Sume
17478064Sume	pthread_mutex_lock(&mutex);
17578064Sume	ep = getauevent_r_locked(e);
17678064Sume	pthread_mutex_unlock(&mutex);
17778064Sume	return (ep);
17878064Sume}
17978064Sume
18078064Sumestruct au_event_ent *
18178064Sumegetauevent(void)
18278064Sume{
18378064Sume	static char event_ent_name[AU_EVENT_NAME_MAX];
18478064Sume	static char event_ent_desc[AU_EVENT_DESC_MAX];
18578064Sume	static struct au_event_ent e;
18678064Sume
18778064Sume	bzero(&e, sizeof(e));
18878064Sume	bzero(event_ent_name, sizeof(event_ent_name));
18978064Sume	bzero(event_ent_desc, sizeof(event_ent_desc));
19078064Sume	e.ae_name = event_ent_name;
19178064Sume	e.ae_desc = event_ent_desc;
19278064Sume	return (getauevent_r(&e));
19378064Sume}
19478064Sume
19578064Sume/*
19678064Sume * Search for an audit event structure having the given event name.
19778064Sume *
19878064Sume * XXXRW: Why accept NULL name?
19978064Sume */
20078064Sumestatic struct au_event_ent *
20178064Sumegetauevnam_r_locked(struct au_event_ent *e, const char *name)
20278064Sume{
203120913Sume	char *nl;
20478064Sume
20578064Sume	if (name == NULL)
20678064Sume		return (NULL);
20778064Sume
20878064Sume	/* Rewind to beginning of the file. */
20978064Sume	setauevent_locked();
21078064Sume
21178064Sume	if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL))
21278064Sume		return (NULL);
21378064Sume
21478064Sume	while (fgets(linestr, AU_LINE_MAX, fp) != NULL) {
21578064Sume		/* Remove new lines. */
21678064Sume		if ((nl = strrchr(linestr, '\n')) != NULL)
21778064Sume			*nl = '\0';
21878064Sume
21953541Sshin		if (eventfromstr(linestr, e) != NULL) {
22062587Sitojun			if (strcmp(name, e->ae_name) == 0)
22162587Sitojun				return (e);
22253541Sshin		}
22362587Sitojun	}
22462587Sitojun
22562587Sitojun	return (NULL);
22695023Ssuz}
22753541Sshin
22853541Sshinstruct au_event_ent *
22953541Sshingetauevnam_r(struct au_event_ent *e, const char *name)
23062587Sitojun{
23162587Sitojun	struct au_event_ent *ep;
23262587Sitojun
23362587Sitojun	pthread_mutex_lock(&mutex);
23462587Sitojun	ep = getauevnam_r_locked(e, name);
23553541Sshin	pthread_mutex_unlock(&mutex);
23662587Sitojun	return (ep);
23762587Sitojun}
238120913Sume
23962587Sitojunstruct au_event_ent *
24053541Sshingetauevnam(const char *name)
24162587Sitojun{
24262587Sitojun	static char event_ent_name[AU_EVENT_NAME_MAX];
24362587Sitojun	static char event_ent_desc[AU_EVENT_DESC_MAX];
24462587Sitojun	static struct au_event_ent e;
24562587Sitojun
24662587Sitojun	bzero(&e, sizeof(e));
24762587Sitojun	bzero(event_ent_name, sizeof(event_ent_name));
24853541Sshin	bzero(event_ent_desc, sizeof(event_ent_desc));
24953541Sshin	e.ae_name = event_ent_name;
25062587Sitojun	e.ae_desc = event_ent_desc;
25162587Sitojun	return (getauevnam_r(&e, name));
25253541Sshin}
25362587Sitojun
25462587Sitojun/*
25553541Sshin * Search for an audit event structure having the given event number.
25662587Sitojun */
25762587Sitojunstatic struct au_event_ent *
25862587Sitojungetauevnum_r_locked(struct au_event_ent *e, au_event_t event_number)
25962587Sitojun{
260120049Smdodd	char *nl;
26162587Sitojun
26278064Sume	/* Rewind to beginning of the file. */
26378064Sume	setauevent_locked();
26478064Sume
26578064Sume	if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL))
26662587Sitojun		return (NULL);
26778064Sume
26878064Sume	while (fgets(linestr, AU_LINE_MAX, fp) != NULL) {
26978064Sume		/* Remove new lines. */
27053541Sshin		if ((nl = strrchr(linestr, '\n')) != NULL)
27162587Sitojun			*nl = '\0';
27262587Sitojun
27362587Sitojun		if (eventfromstr(linestr, e) != NULL) {
27453541Sshin			if (event_number == e->ae_number)
27562587Sitojun				return (e);
27662587Sitojun		}
27762587Sitojun	}
27862587Sitojun
27962587Sitojun	return (NULL);
28062587Sitojun}
28162587Sitojun
28262587Sitojunstruct au_event_ent *
28362587Sitojungetauevnum_r(struct au_event_ent *e, au_event_t event_number)
28462587Sitojun{
28562587Sitojun	struct au_event_ent *ep;
28662587Sitojun
28762587Sitojun	pthread_mutex_lock(&mutex);
28862587Sitojun	ep = getauevnum_r_locked(e, event_number);
28962587Sitojun	pthread_mutex_unlock(&mutex);
29062587Sitojun	return (ep);
29162587Sitojun}
29262587Sitojun
29362587Sitojunstruct au_event_ent *
29462587Sitojungetauevnum(au_event_t event_number)
29562587Sitojun{
29662587Sitojun	static char event_ent_name[AU_EVENT_NAME_MAX];
29762587Sitojun	static char event_ent_desc[AU_EVENT_DESC_MAX];
29862587Sitojun	static struct au_event_ent e;
29962587Sitojun
30062587Sitojun	bzero(&e, sizeof(e));
30162587Sitojun	bzero(event_ent_name, sizeof(event_ent_name));
30262587Sitojun	bzero(event_ent_desc, sizeof(event_ent_desc));
30362587Sitojun	e.ae_name = event_ent_name;
30462587Sitojun	e.ae_desc = event_ent_desc;
30562587Sitojun	return (getauevnum_r(&e, event_number));
30662587Sitojun}
30762587Sitojun
30862587Sitojun/*
30962587Sitojun * Search for an audit_event entry with a given event_name and returns the
31062587Sitojun * corresponding event number.
31162587Sitojun */
31262587Sitojunau_event_t *
31362587Sitojungetauevnonam_r(au_event_t *ev, const char *event_name)
31462587Sitojun{
31562587Sitojun	static char event_ent_name[AU_EVENT_NAME_MAX];
31662587Sitojun	static char event_ent_desc[AU_EVENT_DESC_MAX];
31762587Sitojun	static struct au_event_ent e, *ep;
31862587Sitojun
31953541Sshin	bzero(event_ent_name, sizeof(event_ent_name));
32062587Sitojun	bzero(event_ent_desc, sizeof(event_ent_desc));
32178064Sume	bzero(&e, sizeof(e));
32262587Sitojun	e.ae_name = event_ent_name;
32362587Sitojun	e.ae_desc = event_ent_desc;
32462587Sitojun
32562587Sitojun	ep = getauevnam_r(&e, event_name);
32662587Sitojun	if (ep == NULL)
32762587Sitojun		return (NULL);
32862587Sitojun
32962587Sitojun	*ev = e.ae_number;
33053541Sshin	return (ev);
33162587Sitojun}
33262587Sitojun
33362587Sitojunau_event_t *
33462587Sitojungetauevnonam(const char *event_name)
33562587Sitojun{
33662587Sitojun	static au_event_t event;
33762587Sitojun
33862587Sitojun	return (getauevnonam_r(&event, event_name));
33962587Sitojun}
34062587Sitojun