1185573Srwatson/*-
2185573Srwatson * Copyright (c) 2004 Apple Inc.
3155131Srwatson * Copyright (c) 2006 Robert N. M. Watson
4155131Srwatson * All rights reserved.
5155131Srwatson *
6155131Srwatson * Redistribution and use in source and binary forms, with or without
7155131Srwatson * modification, are permitted provided that the following conditions
8155131Srwatson * are met:
9155131Srwatson * 1.  Redistributions of source code must retain the above copyright
10155131Srwatson *     notice, this list of conditions and the following disclaimer.
11155131Srwatson * 2.  Redistributions in binary form must reproduce the above copyright
12155131Srwatson *     notice, this list of conditions and the following disclaimer in the
13155131Srwatson *     documentation and/or other materials provided with the distribution.
14243750Srwatson * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
15155131Srwatson *     its contributors may be used to endorse or promote products derived
16155131Srwatson *     from this software without specific prior written permission.
17155131Srwatson *
18155131Srwatson * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
19155131Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20155131Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21155131Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
22155131Srwatson * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23155131Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24155131Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25155131Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26155131Srwatson * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27155131Srwatson * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28155131Srwatson * POSSIBILITY OF SUCH DAMAGE.
29155131Srwatson *
30243750Srwatson * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_class.c#16 $
31155131Srwatson */
32155131Srwatson
33185573Srwatson#include <config/config.h>
34185573Srwatson
35155131Srwatson#include <bsm/libbsm.h>
36155131Srwatson
37155131Srwatson#include <string.h>
38186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
39155131Srwatson#include <pthread.h>
40186647Srwatson#endif
41155131Srwatson#include <stdio.h>
42155131Srwatson#include <stdlib.h>
43155131Srwatson
44185573Srwatson#ifndef HAVE_STRLCPY
45185573Srwatson#include <compat/strlcpy.h>
46185573Srwatson#endif
47185573Srwatson
48155131Srwatson/*
49155131Srwatson * Parse the contents of the audit_class file to return struct au_class_ent
50155131Srwatson * entries.
51155131Srwatson */
52155131Srwatsonstatic FILE		*fp = NULL;
53155131Srwatsonstatic char		 linestr[AU_LINE_MAX];
54155131Srwatsonstatic const char	*classdelim = ":";
55155131Srwatson
56186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
57155131Srwatsonstatic pthread_mutex_t	mutex = PTHREAD_MUTEX_INITIALIZER;
58186647Srwatson#endif
59155131Srwatson
60155131Srwatson/*
61155131Srwatson * Parse a single line from the audit_class file passed in str to the struct
62155131Srwatson * au_class_ent elements; store the result in c.
63155131Srwatson */
64155131Srwatsonstatic struct au_class_ent *
65155131Srwatsonclassfromstr(char *str, struct au_class_ent *c)
66155131Srwatson{
67155131Srwatson	char *classname, *classdesc, *classflag;
68155131Srwatson	char *last;
69155131Srwatson
70155131Srwatson	/* Each line contains flag:name:desc. */
71155131Srwatson	classflag = strtok_r(str, classdelim, &last);
72155131Srwatson	classname = strtok_r(NULL, classdelim, &last);
73155131Srwatson	classdesc = strtok_r(NULL, classdelim, &last);
74155131Srwatson
75155131Srwatson	if ((classflag == NULL) || (classname == NULL) || (classdesc == NULL))
76155131Srwatson		return (NULL);
77155131Srwatson
78155131Srwatson	/*
79155131Srwatson	 * Check for very large classnames.
80155131Srwatson	 */
81155131Srwatson	if (strlen(classname) >= AU_CLASS_NAME_MAX)
82155131Srwatson		return (NULL);
83185573Srwatson	strlcpy(c->ac_name, classname, AU_CLASS_NAME_MAX);
84155131Srwatson
85155131Srwatson	/*
86155131Srwatson	 * Check for very large class description.
87155131Srwatson	 */
88155131Srwatson	if (strlen(classdesc) >= AU_CLASS_DESC_MAX)
89155131Srwatson		return (NULL);
90185573Srwatson	strlcpy(c->ac_desc, classdesc, AU_CLASS_DESC_MAX);
91155131Srwatson	c->ac_class = strtoul(classflag, (char **) NULL, 0);
92155131Srwatson
93155131Srwatson	return (c);
94155131Srwatson}
95155131Srwatson
96155131Srwatson/*
97155131Srwatson * Return the next au_class_ent structure from the file setauclass should be
98155131Srwatson * called before invoking this function for the first time.
99155131Srwatson *
100155131Srwatson * Must be called with mutex held.
101155131Srwatson */
102155131Srwatsonstatic struct au_class_ent *
103155131Srwatsongetauclassent_r_locked(struct au_class_ent *c)
104155131Srwatson{
105155131Srwatson	char *tokptr, *nl;
106155131Srwatson
107155131Srwatson	if ((fp == NULL) && ((fp = fopen(AUDIT_CLASS_FILE, "r")) == NULL))
108155131Srwatson		return (NULL);
109155131Srwatson
110155131Srwatson	/*
111155131Srwatson	 * Read until next non-comment line is found, or EOF.
112155131Srwatson	 */
113155131Srwatson	while (1) {
114155131Srwatson		if (fgets(linestr, AU_LINE_MAX, fp) == NULL)
115155131Srwatson			return (NULL);
116155131Srwatson
117155131Srwatson		/* Skip comments. */
118155131Srwatson		if (linestr[0] == '#')
119155131Srwatson			continue;
120155131Srwatson
121155131Srwatson		/* Remove trailing new line character. */
122155131Srwatson		if ((nl = strrchr(linestr, '\n')) != NULL)
123155131Srwatson			*nl = '\0';
124155131Srwatson
125155131Srwatson		/* Parse tokptr to au_class_ent components. */
126155131Srwatson		tokptr = linestr;
127155131Srwatson		if (classfromstr(tokptr, c) == NULL)
128155131Srwatson			return (NULL);
129155131Srwatson		break;
130155131Srwatson	}
131155131Srwatson
132155131Srwatson	return (c);
133155131Srwatson}
134155131Srwatson
135155131Srwatsonstruct au_class_ent *
136155131Srwatsongetauclassent_r(struct au_class_ent *c)
137155131Srwatson{
138155131Srwatson	struct au_class_ent *cp;
139155131Srwatson
140186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
141155131Srwatson	pthread_mutex_lock(&mutex);
142186647Srwatson#endif
143155131Srwatson	cp = getauclassent_r_locked(c);
144186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
145155131Srwatson	pthread_mutex_unlock(&mutex);
146186647Srwatson#endif
147155131Srwatson	return (cp);
148155131Srwatson}
149155131Srwatson
150155131Srwatsonstruct au_class_ent *
151155131Srwatsongetauclassent(void)
152155131Srwatson{
153155131Srwatson	static char class_ent_name[AU_CLASS_NAME_MAX];
154155131Srwatson	static char class_ent_desc[AU_CLASS_DESC_MAX];
155155131Srwatson	static struct au_class_ent c, *cp;
156155131Srwatson
157155131Srwatson	bzero(&c, sizeof(c));
158155131Srwatson	bzero(class_ent_name, sizeof(class_ent_name));
159155131Srwatson	bzero(class_ent_desc, sizeof(class_ent_desc));
160155131Srwatson	c.ac_name = class_ent_name;
161155131Srwatson	c.ac_desc = class_ent_desc;
162155131Srwatson
163186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
164155131Srwatson	pthread_mutex_lock(&mutex);
165186647Srwatson#endif
166155131Srwatson	cp = getauclassent_r_locked(&c);
167186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
168155131Srwatson	pthread_mutex_unlock(&mutex);
169186647Srwatson#endif
170155131Srwatson	return (cp);
171155131Srwatson}
172155131Srwatson
173155131Srwatson/*
174155131Srwatson * Rewind to the beginning of the enumeration.
175155131Srwatson *
176155131Srwatson * Must be called with mutex held.
177155131Srwatson */
178155131Srwatsonstatic void
179155131Srwatsonsetauclass_locked(void)
180155131Srwatson{
181155131Srwatson
182155131Srwatson	if (fp != NULL)
183155131Srwatson		fseek(fp, 0, SEEK_SET);
184155131Srwatson}
185155131Srwatson
186155131Srwatsonvoid
187155131Srwatsonsetauclass(void)
188155131Srwatson{
189155131Srwatson
190186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
191155131Srwatson	pthread_mutex_lock(&mutex);
192186647Srwatson#endif
193155131Srwatson	setauclass_locked();
194186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
195155131Srwatson	pthread_mutex_unlock(&mutex);
196186647Srwatson#endif
197155131Srwatson}
198155131Srwatson
199155131Srwatson/*
200155131Srwatson * Return the next au_class_entry having the given class name.
201155131Srwatson */
202155131Srwatsonstruct au_class_ent *
203155131Srwatsongetauclassnam_r(struct au_class_ent *c, const char *name)
204155131Srwatson{
205155131Srwatson	struct au_class_ent *cp;
206155131Srwatson
207155131Srwatson	if (name == NULL)
208155131Srwatson		return (NULL);
209155131Srwatson
210186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
211155131Srwatson	pthread_mutex_lock(&mutex);
212186647Srwatson#endif
213155131Srwatson	setauclass_locked();
214155131Srwatson	while ((cp = getauclassent_r_locked(c)) != NULL) {
215155131Srwatson		if (strcmp(name, cp->ac_name) == 0) {
216186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
217155131Srwatson			pthread_mutex_unlock(&mutex);
218186647Srwatson#endif
219155131Srwatson			return (cp);
220155131Srwatson		}
221155131Srwatson	}
222186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
223155131Srwatson	pthread_mutex_unlock(&mutex);
224186647Srwatson#endif
225155131Srwatson	return (NULL);
226155131Srwatson}
227155131Srwatson
228155131Srwatsonstruct au_class_ent *
229155131Srwatsongetauclassnam(const char *name)
230155131Srwatson{
231155131Srwatson	static char class_ent_name[AU_CLASS_NAME_MAX];
232155131Srwatson	static char class_ent_desc[AU_CLASS_DESC_MAX];
233155131Srwatson	static struct au_class_ent c;
234155131Srwatson
235155131Srwatson	bzero(&c, sizeof(c));
236155131Srwatson	bzero(class_ent_name, sizeof(class_ent_name));
237155131Srwatson	bzero(class_ent_desc, sizeof(class_ent_desc));
238155131Srwatson	c.ac_name = class_ent_name;
239155131Srwatson	c.ac_desc = class_ent_desc;
240155131Srwatson
241155131Srwatson	return (getauclassnam_r(&c, name));
242155131Srwatson}
243155131Srwatson
244155131Srwatson
245155131Srwatson/*
246155131Srwatson * Return the next au_class_entry having the given class number.
247155131Srwatson *
248155131Srwatson * OpenBSM extension.
249155131Srwatson */
250155131Srwatsonstruct au_class_ent *
251155131Srwatsongetauclassnum_r(struct au_class_ent *c, au_class_t class_number)
252155131Srwatson{
253155131Srwatson	struct au_class_ent *cp;
254155131Srwatson
255186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
256155131Srwatson	pthread_mutex_lock(&mutex);
257186647Srwatson#endif
258155131Srwatson	setauclass_locked();
259155131Srwatson	while ((cp = getauclassent_r_locked(c)) != NULL) {
260155131Srwatson		if (class_number == cp->ac_class)
261155131Srwatson			return (cp);
262155131Srwatson	}
263186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
264155131Srwatson	pthread_mutex_unlock(&mutex);
265186647Srwatson#endif
266155131Srwatson	return (NULL);
267155131Srwatson}
268155131Srwatson
269155131Srwatsonstruct au_class_ent *
270155131Srwatsongetauclassnum(au_class_t class_number)
271155131Srwatson{
272155131Srwatson	static char class_ent_name[AU_CLASS_NAME_MAX];
273155131Srwatson	static char class_ent_desc[AU_CLASS_DESC_MAX];
274155131Srwatson	static struct au_class_ent c;
275155131Srwatson
276155131Srwatson	bzero(&c, sizeof(c));
277155131Srwatson	bzero(class_ent_name, sizeof(class_ent_name));
278155131Srwatson	bzero(class_ent_desc, sizeof(class_ent_desc));
279155131Srwatson	c.ac_name = class_ent_name;
280155131Srwatson	c.ac_desc = class_ent_desc;
281155131Srwatson
282155131Srwatson	return (getauclassnum_r(&c, class_number));
283155131Srwatson}
284155131Srwatson
285155131Srwatson/*
286155131Srwatson * audit_class processing is complete; close any open files.
287155131Srwatson */
288155131Srwatsonvoid
289155131Srwatsonendauclass(void)
290155131Srwatson{
291155131Srwatson
292186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
293155131Srwatson	pthread_mutex_lock(&mutex);
294186647Srwatson#endif
295155131Srwatson	if (fp != NULL) {
296155131Srwatson		fclose(fp);
297155131Srwatson		fp = NULL;
298155131Srwatson	}
299186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
300155131Srwatson	pthread_mutex_unlock(&mutex);
301186647Srwatson#endif
302155131Srwatson}
303