]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - contrib/openbsm/libbsm/bsm_event.c
- Copy stable/10@296371 to releng/10.3 in preparation for 10.3-RC1
[FreeBSD/releng/10.3.git] / contrib / openbsm / libbsm / bsm_event.c
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 *
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
108 setauevent_locked(void)
109 {
110
111         if (fp != NULL)
112                 fseek(fp, 0, SEEK_SET);
113 }
114
115 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
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
356 getauevnonam(const char *event_name)
357 {
358         static au_event_t event;
359
360         return (getauevnonam_r(&event, event_name));
361 }