xref: /titanic_52/usr/src/lib/libbsm/common/audit_event.c (revision bdfc6d18da790deeec2e0eb09c625902defe2498)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 #pragma ident	"%Z%%M%	%I%	%E% SMI"
23 
24 #ifndef lint
25 static char	sccsid[] = "%Z%%M% %I% %E% SMI";
26 #endif
27 
28 /*
29  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
30  * Use is subject to license terms.
31  */
32 
33 /*
34  * Interfaces to audit_event(5)  (/etc/security/audit_event)
35  */
36 
37 /*
38  * This routine is obsolete.  I have removed its inclusion by removing
39  * the .o from the makefile.  Please use cacheauevent() or any of the
40  * getauev* routines.
41  */
42 
43 #include <sys/types.h>
44 #include <limits.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <bsm/audit.h>
49 #include <bsm/libbsm.h>
50 #include <synch.h>
51 
52 /*
53  *	Macros to produce a quoted string containing the value of a
54  *	preprocessor macro. For example, if SIZE is defined to be 256,
55  *	VAL2STR(SIZE) is "256". This is used to construct format
56  *	strings for scanf-family functions below.
57  */
58 #define	QUOTE(x)	#x
59 #define	VAL2STR(x)	QUOTE(x)
60 
61 static au_class_t flagstohex(char *);
62 
63 static char	au_event_fname[PATH_MAX] = AUDITEVENTFILE;
64 static FILE *au_event_file = (FILE *)0;
65 static mutex_t mutex_eventfile = DEFAULTMUTEX;
66 static mutex_t mutex_eventcache = DEFAULTMUTEX;
67 
68 extern int _mutex_lock(mutex_t *);
69 extern int _mutex_unlock(mutex_t *);
70 
71 int
72 #ifdef __STDC__
73 setaueventfile(char *fname)
74 #else
75 setaueventfile(fname)
76 	char	*fname;
77 #endif
78 {
79 	_mutex_lock(&mutex_eventfile);
80 	if (fname) {
81 		(void) strcpy(au_event_fname, fname);
82 	}
83 	_mutex_unlock(&mutex_eventfile);
84 	return (0);
85 }
86 
87 
88 void
89 setauevent()
90 {
91 	_mutex_lock(&mutex_eventfile);
92 	if (au_event_file) {
93 		(void) fseek(au_event_file, 0L, 0);
94 	}
95 	_mutex_unlock(&mutex_eventfile);
96 }
97 
98 
99 void
100 endauevent()
101 {
102 	_mutex_lock(&mutex_eventfile);
103 	if (au_event_file) {
104 		(void) fclose(au_event_file);
105 		au_event_file = (FILE *)0;
106 	}
107 	_mutex_unlock(&mutex_eventfile);
108 }
109 
110 au_event_ent_t *
111 getauevent()
112 {
113 	static au_event_ent_t au_event_entry;
114 	static char	ename[AU_EVENT_NAME_MAX];
115 	static char	edesc[AU_EVENT_DESC_MAX];
116 
117 	/* initialize au_event_entry structure */
118 	au_event_entry.ae_name = ename;
119 	au_event_entry.ae_desc = edesc;
120 
121 	return (getauevent_r(&au_event_entry));
122 }
123 
124 au_event_ent_t *
125 getauevent_r(au_event_entry)
126 	au_event_ent_t *au_event_entry;
127 {
128 	int	i, error = 0, found = 0;
129 	char	*s, input[AU_EVENT_LINE_MAX];
130 	char	trim_buf[AU_EVENT_NAME_MAX+1];
131 
132 	/* open audit event file if it isn't already */
133 	_mutex_lock(&mutex_eventfile);
134 	if (!au_event_file)
135 		if (!(au_event_file = fopen(au_event_fname, "r"))) {
136 			_mutex_unlock(&mutex_eventfile);
137 			return ((au_event_ent_t *)0);
138 		}
139 
140 	while (fgets(input, AU_EVENT_LINE_MAX, au_event_file)) {
141 		if (input[0] != '#') {
142 			s = input + strspn(input, " \t\r\n");
143 			if ((*s == '\0') || (*s == '#')) {
144 				continue;
145 			}
146 			found = 1;
147 			s = input;
148 
149 			/* parse number */
150 			i = strcspn(s, ":");
151 			s[i] = '\0';
152 			(void) sscanf(s, "%hd", &au_event_entry->ae_number);
153 			s = &s[i+1];
154 
155 			/* parse event name */
156 			i = strcspn(s, ":");
157 			s[i] = '\0';
158 			(void) sscanf(s, "%" VAL2STR(AU_EVENT_NAME_MAX) "s",
159 			    trim_buf);
160 			(void) strncpy(au_event_entry->ae_name, trim_buf,
161 				AU_EVENT_NAME_MAX);
162 			s = &s[i+1];
163 
164 			/* parse event description */
165 			i = strcspn(s, ":");
166 			s[i] = '\0';
167 			(void) strncpy(au_event_entry->ae_desc, s,
168 				AU_EVENT_DESC_MAX);
169 			s = &s[i+1];
170 
171 			/* parse class */
172 			i = strcspn(s, "\n\0");
173 			s[i] = '\0';
174 			(void) sscanf(s, "%" VAL2STR(AU_EVENT_NAME_MAX) "s",
175 			    trim_buf);
176 			au_event_entry->ae_class = flagstohex(trim_buf);
177 
178 			break;
179 		}
180 	}
181 	_mutex_unlock(&mutex_eventfile);
182 
183 	if (!error && found) {
184 		return (au_event_entry);
185 	} else {
186 		return ((au_event_ent_t *)0);
187 	}
188 }
189 
190 
191 au_event_ent_t *
192 #ifdef __STDC__
193 getauevnam(char *name)
194 #else
195 getauevnam(name)
196 	char *name;
197 #endif
198 {
199 	static au_event_ent_t au_event_entry;
200 	static char	ename[AU_EVENT_NAME_MAX];
201 	static char	edesc[AU_EVENT_DESC_MAX];
202 
203 	/* initialize au_event_entry structure */
204 	au_event_entry.ae_name = ename;
205 	au_event_entry.ae_desc = edesc;
206 
207 	return (getauevnam_r(&au_event_entry, name));
208 }
209 
210 au_event_ent_t *
211 #ifdef __STDC__
212 getauevnam_r(au_event_ent_t *e, char *name)
213 #else
214 getauevnam_r(e, name)
215 	au_event_ent_t &e;
216 	char *name;
217 #endif
218 {
219 	setauevent();
220 	while (getauevent_r(e) != NULL) {
221 		if (strcmp(e->ae_name, name) == 0) {
222 			endauevent();
223 			return (e);
224 		}
225 	}
226 	endauevent();
227 	return ((au_event_ent_t *)NULL);
228 }
229 
230 au_event_ent_t *
231 #ifdef __STDC__
232 getauevnum_r(au_event_ent_t *e, au_event_t event_number)
233 #else
234 getauevnum_r(e, event_number)
235 	au_event_ent_t *e;
236 	au_event_t event_number;
237 #endif
238 {
239 	setauevent();
240 	while (getauevent_r(e) != NULL) {
241 		if (e->ae_number == event_number) {
242 			endauevent();
243 			return (e);
244 		}
245 	}
246 	endauevent();
247 	return ((au_event_ent_t *)NULL);
248 }
249 
250 au_event_ent_t *
251 #ifdef __STDC__
252 getauevnum(au_event_t event_number)
253 #else
254 getauevnum(event_number)
255 	au_event_t event_number;
256 #endif
257 {
258 	static au_event_ent_t e;
259 	static char	ename[AU_EVENT_NAME_MAX];
260 	static char	edesc[AU_EVENT_DESC_MAX];
261 
262 	/* initialize au_event_entry structure */
263 	e.ae_name = ename;
264 	e.ae_desc = edesc;
265 
266 	return (getauevnum_r(&e, event_number));
267 }
268 
269 au_event_t
270 #ifdef __STDC__
271 getauevnonam(char *event_name)
272 #else
273 getauevnonam(event_name)
274 	char	*event_name;
275 #endif
276 {
277 	au_event_ent_t e;
278 	char ename[AU_EVENT_NAME_MAX];
279 	char edesc[AU_EVENT_DESC_MAX];
280 
281 	/* initialize au_event_entry structure */
282 	e.ae_name = ename;
283 	e.ae_desc = edesc;
284 
285 	if (getauevnam_r(&e, event_name) == (au_event_ent_t *)0) {
286 		return (-1);
287 	}
288 	return (e.ae_number);
289 }
290 
291 /*
292  * cacheauevent:
293  *	Read the entire audit_event file into memory.
294  *	Set a pointer to the requested entry in the cache
295  *	or a pointer to an invalid entry if the event number
296  *	is not known.
297  *
298  *	Return < 0, if error.
299  *	Return   0, if event number not in cache.
300  *	Return   1, if event number is in cache.
301  */
302 
303 int
304 #ifdef __STDC__
305 cacheauevent(au_event_ent_t **result, au_event_t event_number)
306 #else
307 cacheauevent(result, event_number)
308 	au_event_ent_t **result; /* set this pointer to an entry in the cache */
309 	au_event_t event_number; /* request this event number */
310 #endif
311 {
312 	static ushort_t	max; /* the highest event number in the file */
313 	static ushort_t	min; /* the lowest event number in the file */
314 	static int	invalid; /* 1+index of the highest event number */
315 	static au_event_ent_t **index_tbl;
316 	static au_event_ent_t **p_tbl;
317 	static int	called_once = 0;
318 
319 	char	line[AU_EVENT_LINE_MAX];
320 	int	lines = 0;
321 	FILE	*fp;
322 	au_event_ent_t *p_event;
323 	int	i, size;
324 	int	hit = 0;
325 	char	*s;
326 
327 	_mutex_lock(&mutex_eventcache);
328 	if (called_once == 0) {
329 
330 		/* Count number of lines in the events file */
331 		if ((fp = fopen(au_event_fname, "r")) == NULL) {
332 			_mutex_unlock(&mutex_eventcache);
333 			return (-1);
334 		}
335 		while (fgets(line, AU_EVENT_LINE_MAX, fp) != NULL) {
336 			s = line + strspn(line, " \t\r\n");
337 			if ((*s == '\0') || (*s == '#')) {
338 				continue;
339 			}
340 			lines++;
341 		}
342 		(void) fclose(fp);
343 		size = lines;
344 
345 		/*
346 		 * Make an array in which each element in an entry in the
347 		 * events file.  Make the next to last element an invalid
348 		 * event.  Make the last element a NULL pointer.
349 		 */
350 
351 		p_tbl = calloc(lines + 1, sizeof (au_event_ent_t));
352 		if (p_tbl == NULL) {
353 			_mutex_unlock(&mutex_eventcache);
354 			return (-2);
355 		}
356 		lines = 0;
357 		max = 0;
358 		min = 65535;
359 		setauevent();
360 		while ((p_event = getauevent()) != NULL) {
361 			p_tbl[lines] = (au_event_ent_t *)
362 				malloc(sizeof (au_event_ent_t));
363 			if (p_tbl[lines] == NULL) {
364 				_mutex_unlock(&mutex_eventcache);
365 				return (-3);
366 			}
367 			p_tbl[lines]->ae_number = p_event->ae_number;
368 			p_tbl[lines]->ae_name   = strdup(p_event->ae_name);
369 			p_tbl[lines]->ae_desc   = strdup(p_event->ae_desc);
370 			p_tbl[lines]->ae_class  = p_event->ae_class;
371 #ifdef DEBUG2
372 			printevent(p_tbl[lines]);
373 #endif
374 			if ((ushort_t)p_event->ae_number > max) {
375 				max = p_event->ae_number;
376 			}
377 			if ((ushort_t)p_event->ae_number < min) {
378 				min = p_event->ae_number;
379 			}
380 			lines++;
381 		}
382 		endauevent();
383 		invalid = lines;
384 		p_tbl[invalid] = (au_event_ent_t *)
385 			malloc(sizeof (au_event_ent_t));
386 		if (p_tbl[invalid] == NULL) {
387 			_mutex_unlock(&mutex_eventcache);
388 			return (-4);
389 		}
390 		p_tbl[invalid]->ae_number = -1;
391 		p_tbl[invalid]->ae_name   = "invalid event number";
392 		p_tbl[invalid]->ae_desc   = p_tbl[invalid]->ae_name;
393 		p_tbl[invalid]->ae_class  = (au_class_t)-1;
394 
395 #ifdef DEBUG2
396 		for (i = 0; i < size; i++) {
397 			printf("%d:%s:%s:%d\n", p_tbl[i]->ae_number,
398 				p_tbl[i]->ae_name, p_tbl[i]->ae_desc,
399 				p_tbl[i]->ae_class);
400 		}
401 #endif
402 
403 		/* get space for the index_tbl */
404 		index_tbl = calloc(max+1, sizeof (au_event_ent_t *));
405 		if (index_tbl == NULL) {
406 			_mutex_unlock(&mutex_eventcache);
407 			return (-5);
408 		}
409 
410 		/* intialize the index_tbl to the invalid event number */
411 		for (i = 0; (ushort_t)i < max; i++) {
412 			index_tbl[i] = p_tbl[invalid];
413 		}
414 
415 		/* point each index_tbl element at the corresponding event */
416 		for (i = 0; i < size; i++) {
417 			index_tbl[(ushort_t)p_tbl[i]->ae_number] = p_tbl[i];
418 		}
419 
420 		called_once = 1;
421 
422 	}
423 
424 	if ((ushort_t)event_number > max || (ushort_t)event_number < min) {
425 		*result = index_tbl[invalid];
426 	} else {
427 		*result = index_tbl[(ushort_t)event_number];
428 		hit = 1;
429 	}
430 	_mutex_unlock(&mutex_eventcache);
431 	return (hit);
432 }
433 
434 
435 static au_class_t
436 flagstohex(char *flags)
437 {
438 	au_class_ent_t *p_class;
439 	unsigned int	hex = 0;
440 	char	*comma = ",";
441 	char	*s;
442 	char	*last;
443 
444 	s = strtok_r(flags, comma, &last);
445 	while (s != NULL) {
446 		(void) cacheauclassnam(&p_class, s);
447 		hex |= p_class->ac_class;
448 		s = strtok_r(NULL, comma, &last);
449 	}
450 	return (hex);
451 }
452 
453 
454 #ifdef DEBUG2
455 void
456 printevent(p_event)
457 au_event_ent_t *p_event;
458 {
459 	printf("%d:%s:%s:%d\n", p_event->ae_number, p_event->ae_name,
460 		p_event->ae_desc, p_event->ae_class);
461 	fflush(stdout);
462 }
463 
464 
465 #endif
466