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 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
29 * Interfaces to audit_event(5) (/etc/security/audit_event)
33 * This routine is obsolete. I have removed its inclusion by removing
34 * the .o from the makefile. Please use cacheauevent() or any of the
38 #include <sys/types.h>
43 #include <bsm/audit.h>
44 #include <bsm/libbsm.h>
48 * Macros to produce a quoted string containing the value of a
49 * preprocessor macro. For example, if SIZE is defined to be 256,
50 * VAL2STR(SIZE) is "256". This is used to construct format
51 * strings for scanf-family functions below.
54 #define VAL2STR(x) QUOTE(x)
56 static au_class_t
flagstohex(char *);
58 static char au_event_fname
[PATH_MAX
] = AUDITEVENTFILE
;
59 static FILE *au_event_file
= (FILE *)0;
60 static mutex_t mutex_eventfile
= DEFAULTMUTEX
;
61 static mutex_t mutex_eventcache
= DEFAULTMUTEX
;
63 * If an error occurs during the call to cacheauclassnam() inside
64 * flagstohex() any return value could be seen as a valid class mask so
65 * the following global variable, cacheauclass_failure, is set to indicate
66 * that an error has occurred.
68 static int cacheauclass_failure
= 0;
72 printevent(au_event_ent_t
*p_event
)
74 (void) printf("%d:%s:%s:%d\n", p_event
->ae_number
, p_event
->ae_name
,
75 p_event
->ae_desc
, p_event
->ae_class
);
76 (void) fflush(stdout
);
83 (void) mutex_lock(&mutex_eventfile
);
85 (void) fseek(au_event_file
, 0L, 0);
87 (void) mutex_unlock(&mutex_eventfile
);
93 (void) mutex_lock(&mutex_eventfile
);
95 (void) fclose(au_event_file
);
96 au_event_file
= (FILE *)0;
98 (void) mutex_unlock(&mutex_eventfile
);
104 static au_event_ent_t au_event_entry
;
105 static char ename
[AU_EVENT_NAME_MAX
];
106 static char edesc
[AU_EVENT_DESC_MAX
];
108 /* initialize au_event_entry structure */
109 au_event_entry
.ae_name
= ename
;
110 au_event_entry
.ae_desc
= edesc
;
112 return (getauevent_r(&au_event_entry
));
116 getauevent_r(au_event_ent_t
*au_event_entry
)
118 int i
, error
= 0, found
= 0;
119 char *s
, input
[AU_EVENT_LINE_MAX
];
120 char trim_buf
[AU_EVENT_NAME_MAX
+1];
122 /* open audit event file if it isn't already */
123 (void) mutex_lock(&mutex_eventfile
);
125 if (!(au_event_file
= fopen(au_event_fname
, "rF"))) {
126 (void) mutex_unlock(&mutex_eventfile
);
130 while (fgets(input
, AU_EVENT_LINE_MAX
, au_event_file
)) {
131 if (input
[0] != '#') {
132 s
= input
+ strspn(input
, " \t\r\n");
133 if ((*s
== '\0') || (*s
== '#')) {
142 (void) sscanf(s
, "%hu", &au_event_entry
->ae_number
);
145 /* parse event name */
148 (void) sscanf(s
, "%" VAL2STR(AU_EVENT_NAME_MAX
) "s",
150 (void) strncpy(au_event_entry
->ae_name
, trim_buf
,
154 /* parse event description */
157 (void) strncpy(au_event_entry
->ae_desc
, s
,
162 i
= strcspn(s
, "\n\0");
164 (void) sscanf(s
, "%" VAL2STR(AU_EVENT_NAME_MAX
) "s",
166 au_event_entry
->ae_class
= flagstohex(trim_buf
);
167 if (cacheauclass_failure
== 1) {
169 cacheauclass_failure
= 0;
175 (void) mutex_unlock(&mutex_eventfile
);
177 if (!error
&& found
) {
178 return (au_event_entry
);
185 getauevnam(char *name
)
187 static au_event_ent_t au_event_entry
;
188 static char ename
[AU_EVENT_NAME_MAX
];
189 static char edesc
[AU_EVENT_DESC_MAX
];
191 /* initialize au_event_entry structure */
192 au_event_entry
.ae_name
= ename
;
193 au_event_entry
.ae_desc
= edesc
;
195 return (getauevnam_r(&au_event_entry
, name
));
199 getauevnam_r(au_event_ent_t
*e
, char *name
)
202 while (getauevent_r(e
) != NULL
) {
203 if (strcmp(e
->ae_name
, name
) == 0) {
213 getauevnum_r(au_event_ent_t
*e
, au_event_t event_number
)
216 while (getauevent_r(e
) != NULL
) {
217 if (e
->ae_number
== event_number
) {
227 getauevnum(au_event_t event_number
)
229 static au_event_ent_t e
;
230 static char ename
[AU_EVENT_NAME_MAX
];
231 static char edesc
[AU_EVENT_DESC_MAX
];
233 /* initialize au_event_entry structure */
237 return (getauevnum_r(&e
, event_number
));
241 getauevnonam(char *event_name
)
244 char ename
[AU_EVENT_NAME_MAX
];
245 char edesc
[AU_EVENT_DESC_MAX
];
247 /* initialize au_event_entry structure */
251 if (getauevnam_r(&e
, event_name
) == NULL
) {
254 return (e
.ae_number
);
259 * Read the entire audit_event file into memory.
260 * Set a pointer to the requested entry in the cache
261 * or a pointer to an invalid entry if the event number
264 * Return < 0, if error.
265 * Return 0, if event number not in cache.
266 * Return 1, if event number is in cache.
269 cacheauevent(au_event_ent_t
**result
, au_event_t event_number
)
271 static au_event_t max
; /* the highest event number in the file */
272 static au_event_t min
; /* the lowest event number in the file */
273 static int invalid
; /* 1+index of the highest event number */
274 static au_event_ent_t
**index_tbl
;
275 static au_event_ent_t
**p_tbl
;
276 static int called_once
= 0;
278 char line
[AU_EVENT_LINE_MAX
];
281 au_event_ent_t
*p_event
;
286 (void) mutex_lock(&mutex_eventcache
);
287 if (called_once
== 0) {
289 /* Count number of lines in the events file */
290 if ((fp
= fopen(au_event_fname
, "rF")) == NULL
) {
291 (void) mutex_unlock(&mutex_eventcache
);
294 while (fgets(line
, AU_EVENT_LINE_MAX
, fp
) != NULL
) {
295 s
= line
+ strspn(line
, " \t\r\n");
296 if ((*s
== '\0') || (*s
== '#')) {
305 * Make an array in which each element in an entry in the
306 * events file. Make the next to last element an invalid
307 * event. Make the last element a NULL pointer.
310 p_tbl
= calloc(lines
+ 1, sizeof (au_event_ent_t
));
312 (void) mutex_unlock(&mutex_eventcache
);
319 while ((p_event
= getauevent()) != NULL
) {
320 p_tbl
[lines
] = (au_event_ent_t
*)
321 malloc(sizeof (au_event_ent_t
));
322 if (p_tbl
[lines
] == NULL
) {
323 (void) mutex_unlock(&mutex_eventcache
);
326 p_tbl
[lines
]->ae_number
= p_event
->ae_number
;
327 p_tbl
[lines
]->ae_name
= strdup(p_event
->ae_name
);
328 p_tbl
[lines
]->ae_desc
= strdup(p_event
->ae_desc
);
329 p_tbl
[lines
]->ae_class
= p_event
->ae_class
;
331 printevent(p_tbl
[lines
]);
333 if (p_event
->ae_number
> max
) {
334 max
= p_event
->ae_number
;
336 if (p_event
->ae_number
< min
) {
337 min
= p_event
->ae_number
;
343 p_tbl
[invalid
] = (au_event_ent_t
*)
344 malloc(sizeof (au_event_ent_t
));
345 if (p_tbl
[invalid
] == NULL
) {
346 (void) mutex_unlock(&mutex_eventcache
);
349 p_tbl
[invalid
]->ae_number
= (au_event_t
)-1;
350 p_tbl
[invalid
]->ae_name
= "invalid event number";
351 p_tbl
[invalid
]->ae_desc
= p_tbl
[invalid
]->ae_name
;
352 p_tbl
[invalid
]->ae_class
= (au_class_t
)-1;
355 for (i
= 0; i
< size
; i
++) {
356 (void) printf("%d:%s:%s:%d\n", p_tbl
[i
]->ae_number
,
357 p_tbl
[i
]->ae_name
, p_tbl
[i
]->ae_desc
,
362 /* get space for the index_tbl */
363 index_tbl
= calloc(max
+1, sizeof (au_event_ent_t
*));
364 if (index_tbl
== NULL
) {
365 (void) mutex_unlock(&mutex_eventcache
);
369 /* intialize the index_tbl to the invalid event number */
370 for (i
= 0; (au_event_t
)i
< max
; i
++) {
371 index_tbl
[i
] = p_tbl
[invalid
];
374 /* point each index_tbl element at the corresponding event */
375 for (i
= 0; i
< size
; i
++) {
376 index_tbl
[p_tbl
[i
]->ae_number
] = p_tbl
[i
];
383 if (event_number
> max
|| event_number
< min
) {
384 *result
= index_tbl
[invalid
];
386 *result
= index_tbl
[event_number
];
389 (void) mutex_unlock(&mutex_eventcache
);
394 flagstohex(char *flags
)
396 au_class_ent_t
*p_class
;
402 s
= strtok_r(flags
, comma
, &last
);
404 if ((cacheauclassnam(&p_class
, s
)) < 0) {
405 cacheauclass_failure
= 1;
406 return ((au_class_t
)-1);
408 hex
|= p_class
->ac_class
;
409 s
= strtok_r(NULL
, comma
, &last
);