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