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]
23 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
27 * Interfaces to audit_class(5) (/etc/security/audit_class)
33 #include <sys/types.h>
34 #include <bsm/audit.h>
35 #include <bsm/libbsm.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
;
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
);
56 (void) mutex_lock(&mutex_classfile
);
58 (void) fseek(au_class_file
, 0L, 0);
60 (void) mutex_unlock(&mutex_classfile
);
67 (void) mutex_lock(&mutex_classfile
);
69 (void) fclose(au_class_file
);
72 (void) mutex_unlock(&mutex_classfile
);
77 * This is not MT-safe because of the static variables.
82 static au_class_ent_t e
;
83 static char cname
[AU_CLASS_NAME_MAX
];
84 static char cdesc
[AU_CLASS_DESC_MAX
];
89 return (getauclassent_r(&e
));
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.
100 getauclassent_r(au_class_ent_t
*au_class_entry
)
102 int i
, error
= 0, found
= 0;
106 if (au_class_entry
== (au_class_ent_t
*)NULL
||
107 au_class_entry
->ac_name
== NULL
||
108 au_class_entry
->ac_desc
== 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
);
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
== '#')) {
132 if (strncmp(s
, "0x", 2) == 0) {
133 (void) sscanf(&s
[2], "%x", &v
);
135 (void) sscanf(s
, "%u", &v
);
137 au_class_entry
->ac_class
= v
;
140 /* parse class name */
143 (void) strncpy(au_class_entry
->ac_name
, s
,
147 /* parse class description */
148 i
= strcspn(s
, "\n\0");
150 (void) strncpy(au_class_entry
->ac_desc
, s
,
157 (void) mutex_unlock(&mutex_classfile
);
159 if (!error
&& found
) {
160 return (au_class_entry
);
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
];
177 return (getauclassnam_r(&e
, name
));
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) {
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.
204 xcacheauclass(au_class_ent_t
**result
, char *class_name
, au_class_t class_no
,
208 static au_class_ent_t
**class_tbl
;
209 static int called_once
;
210 static int lines
= 0;
214 au_class_ent_t
*p_class
;
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
);
227 while (fgets(line
, 256, fp
) != NULL
) {
228 s
= line
+ strspn(line
, " \t\r\n");
229 if ((*s
== '\0') || (*s
== '#')) {
235 class_tbl
= (au_class_ent_t
**)calloc((size_t)lines
+ 1,
237 if (class_tbl
== NULL
) {
238 (void) mutex_unlock(&mutex_classcache
);
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
);
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
);
260 printclass(class_tbl
[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
);
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
;
279 for (i
= 0; i
<= lines
; i
++) {
280 printclass(class_tbl
[i
]);
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
];
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
];
304 (void) mutex_unlock(&mutex_classcache
);
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,