xref: /illumos-gate/usr/src/lib/libbsm/common/au_preselect.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * au_preselect.c
29  */
30 
31 #include <sys/types.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <bsm/audit.h>
35 #include <bsm/libbsm.h>
36 #include <synch.h>
37 
38 #define	ALLOC_INIT (600)	/* initially allocate ALLOC_INIT map entries */
39 #define	ALLOC_INCR (100)	/* if more map entries are needed, realloc */
40 				/* in ALLOC_INCR increments */
41 
42 static int alloc_map();
43 static int load_map();
44 static int realloc_map();
45 
46 typedef struct event_map {
47 	au_event_t event;	/* audit event number */
48 	au_class_t class;	/* audit event class mask */
49 } event_map_t;
50 
51 static event_map_t *event_map;	/* the map */
52 static uint_t alloc_count;	/* number of entries currently allocated */
53 static uint_t event_count;	/* number of entries in map */
54 static mutex_t mutex_au_preselect = DEFAULTMUTEX;
55 
56 /*
57  * au_preselect:
58  *
59  * Keep a dynamic array of event<-->class mappings.
60  * Refresh the map when the value of flag is AU_PRS_REREAD.
61  * Return:
62  *	1: The event is preselected.
63  *	0: The event is not preselected.
64  *	-1: There was an error:
65  *		Couldn't allocate memory.
66  *		Couldn't find event.
67  */
68 int
69 au_preselect(au_event_t au_event, au_mask_t *au_mask_p, int sorf, int flag)
70 {
71 	static char been_here_before;  /* we cache the map */
72 	register int i;
73 	register au_class_t comp_class;
74 
75 	(void) mutex_lock(&mutex_au_preselect);
76 	if (!been_here_before) {
77 		if (alloc_map() == -1) {
78 			(void) mutex_unlock(&mutex_au_preselect);
79 			return (-1);
80 		}
81 
82 		if (load_map() == -1) {
83 			(void) mutex_unlock(&mutex_au_preselect);
84 			return (-1);
85 		}
86 
87 		been_here_before = 1;
88 	}
89 
90 	/*
91 	 * Don't use the cache. Re-read the audit_event(5) db every time
92 	 */
93 	if (flag == AU_PRS_REREAD) {
94 		if (load_map() == -1) {
95 			(void) mutex_unlock(&mutex_au_preselect);
96 			return (-1);
97 		}
98 	}
99 
100 	/* Determine what portion of the preselection mask to check. */
101 	if (sorf == AU_PRS_SUCCESS)
102 		comp_class = au_mask_p->am_success;
103 	else if (sorf == AU_PRS_FAILURE)
104 		comp_class = au_mask_p->am_failure;
105 	else
106 		comp_class = au_mask_p->am_success | au_mask_p->am_failure;
107 
108 	for (i = 0; i < event_count; i++) {
109 		if (event_map[i].event == au_event) {
110 			if (event_map[i].class & comp_class) {
111 				(void) mutex_unlock(&mutex_au_preselect);
112 				return (1);
113 			} else {
114 				(void) mutex_unlock(&mutex_au_preselect);
115 				return (0);
116 			}
117 		}
118 	}
119 
120 	(void) mutex_unlock(&mutex_au_preselect);
121 	return (-1);	/* could not find event in the table */
122 }
123 
124 /*
125  * Initially allocate about as many map entries as are there
126  * are audit events shipped with the system. For sites
127  * that don't add audit events, this should be enough.
128  */
129 static int
130 alloc_map()
131 {
132 	if ((event_map = (event_map_t *)
133 	    calloc(ALLOC_INIT, (size_t)sizeof (event_map_t))) ==
134 	    (event_map_t *)NULL)
135 		return (-1);
136 	else
137 		alloc_count = ALLOC_INIT;
138 
139 	return (0);
140 }
141 
142 /*
143  * load the event<->class map into memory
144  */
145 static int
146 load_map()
147 {
148 	register au_event_ent_t *evp;
149 
150 	event_count = 0;
151 	setauevent();
152 	while ((evp = getauevent()) != (au_event_ent_t *)NULL) {
153 		if (event_count > alloc_count)
154 			if (realloc_map() == -1) {
155 				endauevent();
156 				return (-1);
157 			}
158 		event_map[event_count].event = evp->ae_number;
159 		event_map[event_count].class = evp->ae_class;
160 		++event_count;
161 	}
162 	endauevent();
163 
164 	return (0);
165 }
166 
167 /*
168  * realloc the event map in ALLOC_INCR increments
169  */
170 static int
171 realloc_map()
172 {
173 	register size_t rsize;
174 	rsize = sizeof (event_map_t) * (alloc_count + ALLOC_INCR);
175 
176 	if ((event_map = (event_map_t *)
177 	    realloc(event_map, rsize)) == (event_map_t *)NULL)
178 		return (-1);
179 
180 	return (0);
181 }
182