]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - contrib/openbsm/libbsm/bsm_class.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / contrib / openbsm / libbsm / bsm_class.c
1 /*
2  * Copyright (c) 2004 Apple Computer, 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 Computer, 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  * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_class.c#11 $
31  */
32
33 #include <bsm/libbsm.h>
34
35 #include <string.h>
36 #include <pthread.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39
40 /*
41  * Parse the contents of the audit_class file to return struct au_class_ent
42  * entries.
43  */
44 static FILE             *fp = NULL;
45 static char              linestr[AU_LINE_MAX];
46 static const char       *classdelim = ":";
47
48 static pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER;
49
50 /*
51  * Parse a single line from the audit_class file passed in str to the struct
52  * au_class_ent elements; store the result in c.
53  */
54 static struct au_class_ent *
55 classfromstr(char *str, struct au_class_ent *c)
56 {
57         char *classname, *classdesc, *classflag;
58         char *last;
59
60         /* Each line contains flag:name:desc. */
61         classflag = strtok_r(str, classdelim, &last);
62         classname = strtok_r(NULL, classdelim, &last);
63         classdesc = strtok_r(NULL, classdelim, &last);
64
65         if ((classflag == NULL) || (classname == NULL) || (classdesc == NULL))
66                 return (NULL);
67
68         /*
69          * Check for very large classnames.
70          */
71         if (strlen(classname) >= AU_CLASS_NAME_MAX)
72                 return (NULL);
73
74         strcpy(c->ac_name, classname);
75
76         /*
77          * Check for very large class description.
78          */
79         if (strlen(classdesc) >= AU_CLASS_DESC_MAX)
80                 return (NULL);
81         strcpy(c->ac_desc, classdesc);
82         c->ac_class = strtoul(classflag, (char **) NULL, 0);
83
84         return (c);
85 }
86
87 /*
88  * Return the next au_class_ent structure from the file setauclass should be
89  * called before invoking this function for the first time.
90  *
91  * Must be called with mutex held.
92  */
93 static struct au_class_ent *
94 getauclassent_r_locked(struct au_class_ent *c)
95 {
96         char *tokptr, *nl;
97
98         if ((fp == NULL) && ((fp = fopen(AUDIT_CLASS_FILE, "r")) == NULL))
99                 return (NULL);
100
101         /*
102          * Read until next non-comment line is found, or EOF.
103          */
104         while (1) {
105                 if (fgets(linestr, AU_LINE_MAX, fp) == NULL)
106                         return (NULL);
107
108                 /* Skip comments. */
109                 if (linestr[0] == '#')
110                         continue;
111
112                 /* Remove trailing new line character. */
113                 if ((nl = strrchr(linestr, '\n')) != NULL)
114                         *nl = '\0';
115
116                 /* Parse tokptr to au_class_ent components. */
117                 tokptr = linestr;
118                 if (classfromstr(tokptr, c) == NULL)
119                         return (NULL);
120                 break;
121         }
122
123         return (c);
124 }
125
126 struct au_class_ent *
127 getauclassent_r(struct au_class_ent *c)
128 {
129         struct au_class_ent *cp;
130
131         pthread_mutex_lock(&mutex);
132         cp = getauclassent_r_locked(c);
133         pthread_mutex_unlock(&mutex);
134         return (cp);
135 }
136
137 struct au_class_ent *
138 getauclassent(void)
139 {
140         static char class_ent_name[AU_CLASS_NAME_MAX];
141         static char class_ent_desc[AU_CLASS_DESC_MAX];
142         static struct au_class_ent c, *cp;
143
144         bzero(&c, sizeof(c));
145         bzero(class_ent_name, sizeof(class_ent_name));
146         bzero(class_ent_desc, sizeof(class_ent_desc));
147         c.ac_name = class_ent_name;
148         c.ac_desc = class_ent_desc;
149
150         pthread_mutex_lock(&mutex);
151         cp = getauclassent_r_locked(&c);
152         pthread_mutex_unlock(&mutex);
153         return (cp);
154 }
155
156 /*
157  * Rewind to the beginning of the enumeration.
158  *
159  * Must be called with mutex held.
160  */
161 static void
162 setauclass_locked(void)
163 {
164
165         if (fp != NULL)
166                 fseek(fp, 0, SEEK_SET);
167 }
168
169 void
170 setauclass(void)
171 {
172
173         pthread_mutex_lock(&mutex);
174         setauclass_locked();
175         pthread_mutex_unlock(&mutex);
176 }
177
178 /*
179  * Return the next au_class_entry having the given class name.
180  */
181 struct au_class_ent *
182 getauclassnam_r(struct au_class_ent *c, const char *name)
183 {
184         struct au_class_ent *cp;
185
186         if (name == NULL)
187                 return (NULL);
188
189         pthread_mutex_lock(&mutex);
190         setauclass_locked();
191         while ((cp = getauclassent_r_locked(c)) != NULL) {
192                 if (strcmp(name, cp->ac_name) == 0) {
193                         pthread_mutex_unlock(&mutex);
194                         return (cp);
195                 }
196         }
197         pthread_mutex_unlock(&mutex);
198         return (NULL);
199 }
200
201 struct au_class_ent *
202 getauclassnam(const char *name)
203 {
204         static char class_ent_name[AU_CLASS_NAME_MAX];
205         static char class_ent_desc[AU_CLASS_DESC_MAX];
206         static struct au_class_ent c;
207
208         bzero(&c, sizeof(c));
209         bzero(class_ent_name, sizeof(class_ent_name));
210         bzero(class_ent_desc, sizeof(class_ent_desc));
211         c.ac_name = class_ent_name;
212         c.ac_desc = class_ent_desc;
213
214         return (getauclassnam_r(&c, name));
215 }
216
217
218 /*
219  * Return the next au_class_entry having the given class number.
220  *
221  * OpenBSM extension.
222  */
223 struct au_class_ent *
224 getauclassnum_r(struct au_class_ent *c, au_class_t class_number)
225 {
226         struct au_class_ent *cp;
227
228         pthread_mutex_lock(&mutex);
229         setauclass_locked();
230         while ((cp = getauclassent_r_locked(c)) != NULL) {
231                 if (class_number == cp->ac_class)
232                         return (cp);
233         }
234         pthread_mutex_unlock(&mutex);
235         return (NULL);
236 }
237
238 struct au_class_ent *
239 getauclassnum(au_class_t class_number)
240 {
241         static char class_ent_name[AU_CLASS_NAME_MAX];
242         static char class_ent_desc[AU_CLASS_DESC_MAX];
243         static struct au_class_ent c;
244
245         bzero(&c, sizeof(c));
246         bzero(class_ent_name, sizeof(class_ent_name));
247         bzero(class_ent_desc, sizeof(class_ent_desc));
248         c.ac_name = class_ent_name;
249         c.ac_desc = class_ent_desc;
250
251         return (getauclassnum_r(&c, class_number));
252 }
253
254 /*
255  * audit_class processing is complete; close any open files.
256  */
257 void
258 endauclass(void)
259 {
260
261         pthread_mutex_lock(&mutex);
262         if (fp != NULL) {
263                 fclose(fp);
264                 fp = NULL;
265         }
266         pthread_mutex_unlock(&mutex);
267 }