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