dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libbsm / common / audit_class.c
blob1d00b9fef7313bc2d76c61ce814be96bcc5d458a
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
27 * Interfaces to audit_class(5) (/etc/security/audit_class)
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <limits.h>
33 #include <sys/types.h>
34 #include <bsm/audit.h>
35 #include <bsm/libbsm.h>
36 #include <string.h>
37 #include <synch.h>
39 static char au_class_fname[PATH_MAX] = AUDITCLASSFILE;
40 static FILE *au_class_file = NULL;
41 static mutex_t mutex_classfile = DEFAULTMUTEX;
42 static mutex_t mutex_classcache = DEFAULTMUTEX;
44 #ifdef DEBUG2
45 void
46 printclass(au_class_ent_t *p_c)
48 (void) printf("%x:%s:%s\n", p_c->ac_class, p_c->ac_name, p_c->ac_desc);
49 (void) fflush(stdout);
51 #endif
53 void
54 setauclass()
56 (void) mutex_lock(&mutex_classfile);
57 if (au_class_file) {
58 (void) fseek(au_class_file, 0L, 0);
60 (void) mutex_unlock(&mutex_classfile);
64 void
65 endauclass()
67 (void) mutex_lock(&mutex_classfile);
68 if (au_class_file) {
69 (void) fclose(au_class_file);
70 au_class_file = NULL;
72 (void) mutex_unlock(&mutex_classfile);
76 * getauclassent():
77 * This is not MT-safe because of the static variables.
79 au_class_ent_t *
80 getauclassent()
82 static au_class_ent_t e;
83 static char cname[AU_CLASS_NAME_MAX];
84 static char cdesc[AU_CLASS_DESC_MAX];
86 e.ac_name = cname;
87 e.ac_desc = cdesc;
89 return (getauclassent_r(&e));
93 * getauclassent_r
94 * This is MT-safe if each thread passes in its own pointer
95 * to the space where the class entry is returned. Becareful
96 * to also allocate space from the cname and cdesc pointers
97 * in the au_class_ent structure.
99 au_class_ent_t *
100 getauclassent_r(au_class_ent_t *au_class_entry)
102 int i, error = 0, found = 0;
103 char *s, input[256];
104 au_class_t v;
106 if (au_class_entry == (au_class_ent_t *)NULL ||
107 au_class_entry->ac_name == NULL ||
108 au_class_entry->ac_desc == NULL) {
109 return (NULL);
112 /* open audit class file if it isn't already */
113 (void) mutex_lock(&mutex_classfile);
114 if (!au_class_file) {
115 if (!(au_class_file = fopen(au_class_fname, "rF"))) {
116 (void) mutex_unlock(&mutex_classfile);
117 return (NULL);
121 while (fgets(input, 256, au_class_file)) {
122 if (input[0] != '#') {
123 s = input + strspn(input, " \t\r\n");
124 if ((*s == '\0') || (*s == '#')) {
125 continue;
127 found = 1;
129 /* parse bitfield */
130 i = strcspn(s, ":");
131 s[i] = '\0';
132 if (strncmp(s, "0x", 2) == 0) {
133 (void) sscanf(&s[2], "%x", &v);
134 } else {
135 (void) sscanf(s, "%u", &v);
137 au_class_entry->ac_class = v;
138 s = &s[i+1];
140 /* parse class name */
141 i = strcspn(s, ":");
142 s[i] = '\0';
143 (void) strncpy(au_class_entry->ac_name, s,
144 AU_CLASS_NAME_MAX);
145 s = &s[i+1];
147 /* parse class description */
148 i = strcspn(s, "\n\0");
149 s[i] = '\0';
150 (void) strncpy(au_class_entry->ac_desc, s,
151 AU_CLASS_DESC_MAX);
153 break;
157 (void) mutex_unlock(&mutex_classfile);
159 if (!error && found) {
160 return (au_class_entry);
161 } else {
162 return (NULL);
167 au_class_ent_t *
168 getauclassnam(char *name)
170 static au_class_ent_t e;
171 static char cname[AU_CLASS_NAME_MAX];
172 static char cdesc[AU_CLASS_DESC_MAX];
174 e.ac_name = cname;
175 e.ac_desc = cdesc;
177 return (getauclassnam_r(&e, name));
180 au_class_ent_t *
181 getauclassnam_r(au_class_ent_t *e, char *name)
183 while (getauclassent_r(e) != NULL) {
184 if (strncmp(e->ac_name, name, AU_CLASS_NAME_MAX) == 0) {
185 return (e);
188 return (NULL);
193 * xcacheauclass:
194 * Read the entire audit_class file into memory.
195 * Return a pointer to the requested entry in the cache
196 * or a pointer to an invalid entry if the the class
197 * requested is not known.
199 * Return < 0, do not set result pointer, if error.
200 * Return 0, set result pointer to invalid entry, if class not in cache.
201 * Return 1, set result pointer to a valid entry, if class is in cache.
203 static int
204 xcacheauclass(au_class_ent_t **result, char *class_name, au_class_t class_no,
205 int flags)
207 static int invalid;
208 static au_class_ent_t **class_tbl;
209 static int called_once;
210 static int lines = 0;
212 char line[256];
213 FILE *fp;
214 au_class_ent_t *p_class;
215 int i;
216 int hit = 0;
217 char *s;
219 (void) mutex_lock(&mutex_classcache);
220 if (called_once == 0) {
222 /* Count number of lines in the class file */
223 if ((fp = fopen(au_class_fname, "rF")) == NULL) {
224 (void) mutex_unlock(&mutex_classcache);
225 return (-1);
227 while (fgets(line, 256, fp) != NULL) {
228 s = line + strspn(line, " \t\r\n");
229 if ((*s == '\0') || (*s == '#')) {
230 continue;
232 lines++;
234 (void) fclose(fp);
235 class_tbl = (au_class_ent_t **)calloc((size_t)lines + 1,
236 sizeof (class_tbl));
237 if (class_tbl == NULL) {
238 (void) mutex_unlock(&mutex_classcache);
239 return (-2);
242 lines = 0;
243 setauclass();
245 * This call to getauclassent is protected by
246 * mutex_classcache, so we don't need to use the thread-
247 * safe version (getauclassent_r).
249 while ((p_class = getauclassent()) != NULL) {
250 class_tbl[lines] = (au_class_ent_t *)
251 malloc(sizeof (au_class_ent_t));
252 if (class_tbl[lines] == NULL) {
253 (void) mutex_unlock(&mutex_classcache);
254 return (-3);
256 class_tbl[lines]->ac_name = strdup(p_class->ac_name);
257 class_tbl[lines]->ac_class = p_class->ac_class;
258 class_tbl[lines]->ac_desc = strdup(p_class->ac_desc);
259 #ifdef DEBUG2
260 printclass(class_tbl[lines]);
261 #endif
262 lines++;
264 endauclass();
265 invalid = lines;
266 class_tbl[invalid] = (au_class_ent_t *)
267 malloc(sizeof (au_class_ent_t));
268 if (class_tbl[invalid] == NULL) {
269 (void) mutex_unlock(&mutex_classcache);
270 return (-4);
272 class_tbl[invalid]->ac_name = "invalid class";
273 class_tbl[invalid]->ac_class = 0;
274 class_tbl[invalid]->ac_desc = class_tbl[invalid]->ac_name;
276 called_once = 1;
278 #ifdef DEBUG2
279 for (i = 0; i <= lines; i++) {
280 printclass(class_tbl[i]);
282 #endif
284 } /* END if called_once */
285 *result = class_tbl[invalid];
286 if (flags & AU_CACHE_NAME) {
287 for (i = 0; i < lines; i++) {
288 if (strncmp(class_name, class_tbl[i]->ac_name,
289 AU_CLASS_NAME_MAX) == 0) {
290 *result = class_tbl[i];
291 hit = 1;
292 break;
295 } else if (flags & AU_CACHE_NUMBER) {
296 for (i = 0; i < lines; i++) {
297 if (class_no == class_tbl[i]->ac_class) {
298 *result = class_tbl[i];
299 hit = 1;
300 break;
304 (void) mutex_unlock(&mutex_classcache);
305 return (hit);
309 cacheauclass(au_class_ent_t **result, au_class_t class_no)
311 return (xcacheauclass(result, "", class_no, AU_CACHE_NUMBER));
315 cacheauclassnam(au_class_ent_t **result, char *class_name)
317 return (xcacheauclass(result, class_name, (au_class_t)0,
318 AU_CACHE_NAME));