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 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * get audit preselection mask values
30  */
31 
32 #include <stdio.h>
33 #include <string.h>
34 #include <syslog.h>
35 #include <sys/types.h>
36 #include <bsm/audit.h>
37 #include <bsm/libbsm.h>
38 
39 #define	ON 1
40 #define	OK 0
41 #define	OFF -1
42 #define	COMMA  ','
43 
44 #define	MAXFLDLEN 25
45 
46 int getauditflagsbin();
47 
48 static int
49 match_class(s, prefix, m, v)
50 char	*s;
51 char	*prefix;
52 unsigned int	m;
53 int	v;
54 {
55 	au_class_ent_t *p_class;
56 
57 	(void) strcat(s, prefix);
58 	if (cacheauclass(&p_class, m) == 1) {
59 		(void) strcat(s, v ? p_class->ac_desc : p_class->ac_name);
60 		(void) strcat(s, ",");
61 		return (0);
62 	}
63 	return (-1);
64 }
65 
66 
67 /*
68  * getauditflagschar() - convert bit flag to character string
69  *
70  * input:	masks->am_success - audit on success
71  *		masks->am_failure - audit on failure
72  *		verbose - string format. 0 if short name; 1 if long name;
73  *
74  * output: auditstring - resultant audit string
75  *
76  * returns: 	0 - entry read ok
77  *		-1 - error
78  */
79 
80 int
81 getauditflagschar(auditstring, masks, verbose)
82 char	*auditstring;
83 au_mask_t *masks;
84 int	verbose;
85 {
86 	char	*prefix;		/* +, -, or null */
87 	unsigned int	m;		/* for masking with masks */
88 	au_mask_t all; 		/* value for the string "all" */
89 	int	plus_all = 0;	/* true if +all */
90 	int	minus_all = 0;	/* true if -all */
91 	int	l;
92 
93 	/* initialize input buffer */
94 	*auditstring = '\0';
95 	/* no masks, no flags; we're outta here */
96 	if ((masks->am_success == 0) && (masks->am_failure == 0)) {
97 		if (match_class(auditstring, "", 0, verbose) != 0)
98 			return (-1);
99 		/* kludge to get rid of trailing comma */
100 		l = strlen(auditstring) - 1;
101 		if (auditstring[l] == COMMA)
102 			auditstring[l] = '\0';
103 		return (0);
104 	}
105 	/* Get the mask value for the string "all" */
106 	all.am_success = 0;
107 	all.am_failure = 0;
108 	if (getauditflagsbin("all", &all) != 0)
109 		return (-1);
110 	if (all.am_success == masks->am_success) {
111 		if (all.am_failure == masks->am_failure) {
112 			(void) strcat(auditstring, "all");
113 			return (0);
114 		}
115 		(void) strcat(auditstring, "+all,");
116 		plus_all = 1;
117 	} else if (all.am_failure == masks->am_failure) {
118 		(void) strcat(auditstring, "-all,");
119 		minus_all = 1;
120 	}
121 	for (m = (unsigned)0x80000000; m != 0; m >>= 1) {
122 		if (m & masks->am_success & masks->am_failure)
123 			prefix = plus_all ? "-" : (minus_all ? "+" : "");
124 		else if (m & masks->am_success)
125 			prefix = "+";
126 		else if (m & masks->am_failure)
127 			prefix = "-";
128 			else
129 			continue;
130 		if (match_class(auditstring, prefix, m, verbose) != 0)
131 			return (-1);
132 	}
133 	if (*(prefix = auditstring + strlen(auditstring) - 1) == COMMA)
134 		*prefix = '\0';
135 	return (0);
136 
137 }
138 
139 /*
140  * getauditflagsbin() -  converts character string to success and
141  *			 failure bit masks
142  *
143  * input:	auditstring - audit string
144  *		cnt - number of elements in the masks array
145  *
146  * output:	masks->am_success - audit on success
147  *		masks->am_failure - audit on failure
148  *
149  * returns: 0 - ok
150  *	    -1 - error - string contains characters which do
151  *		not match event flag names or invalid pointers
152  *              passed in.
153  */
154 
155 int
156 getauditflagsbin(auditstring, masks)
157 char	*auditstring;
158 au_mask_t *masks;
159 {
160 	int	gotone, done = 0, invert = 0, tryagain;
161 	int	retstat = 0, succ_event, fail_event;
162 	char	*ptr, tmp_buff[MAXFLDLEN];
163 	au_class_ent_t *p_class;
164 
165 	if ((masks == NULL) || (auditstring == NULL))
166 		return (-1);
167 
168 	masks->am_success = masks->am_failure = 0;
169 
170 	/* process character string */
171 	do {
172 		gotone = 0;
173 		/* read through string storing chars. until a comma */
174 		for (ptr = tmp_buff; !gotone; /* */) {
175 			if (*auditstring != COMMA && *auditstring != '\0' &&
176 			    *auditstring != '\n' && *auditstring != ' ' &&
177 			    *auditstring != '\t')
178 				*ptr++ = *auditstring++;
179 			else if (*auditstring == ' ' || *auditstring == '\t')
180 				auditstring++;
181 			else {
182 				if (*auditstring == '\0' ||
183 						*auditstring == '\n') {
184 					done = 1;
185 					if (ptr == tmp_buff)
186 						done = 2;
187 				}
188 				gotone = 1;
189 			}
190 		}
191 		/* * process audit state */
192 		if (gotone && done != 2) {
193 			if (!done)
194 				auditstring++;
195 			*ptr++ = '\0';
196 			ptr = tmp_buff;
197 			gotone = 0;
198 			succ_event = ON;
199 			fail_event = ON;
200 			tryagain = 1;
201 			invert = 0;
202 
203 			/* get flags */
204 			do {
205 				switch (*ptr++) {
206 				case '^':
207 					invert = 1;
208 					succ_event = OFF;
209 					fail_event = OFF;
210 					break;
211 				case '+':
212 					if (invert)
213 						fail_event = OK;
214 					else {
215 						succ_event = ON;
216 						fail_event = OK;
217 					}
218 					break;
219 				case '-':
220 					if (invert)
221 						succ_event = OK;
222 					else {
223 						fail_event = ON;
224 						succ_event = OK;
225 					}
226 					break;
227 				default:
228 					tryagain = 0;
229 					ptr--;
230 					break;
231 				}
232 			} while (tryagain);
233 
234 			/* add audit state to mask */
235 
236 
237 			if (cacheauclassnam(&p_class, ptr) == 1) {
238 				if (succ_event == ON)
239 					masks->am_success |= p_class->ac_class;
240 				else if (succ_event == OFF)
241 					masks->am_success &=
242 						~(p_class->ac_class);
243 				if (fail_event == ON)
244 					masks->am_failure |= p_class->ac_class;
245 				else if (fail_event == OFF)
246 					masks->am_failure &=
247 						~(p_class->ac_class);
248 				gotone = 1;
249 			} else {  /* Bug 4330887 */
250 				syslog(LOG_CRIT,
251 					"auditflags have invalid flag %s",
252 					ptr);
253 				continue;
254 			}
255 			if (!gotone) {
256 				retstat = -1;
257 				done = 1;
258 			}
259 		}
260 	} while (!done);
261 
262 
263 	return (retstat);
264 }
265