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 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /*
26 * get audit preselection mask values
27 */
28
29 #include <ctype.h>
30 #include <stdio.h>
31 #include <string.h>
32
33 #include <sys/errno.h>
34 #include <sys/types.h>
35 #include <bsm/audit.h>
36 #include <bsm/libbsm.h>
37
38 #include <adt_xlate.h> /* adt_write_syslog */
39
40 #define SUCCESS 0x1 /* '+' success mask */
41 #define FAILURE 0x2 /* '-' failure mask */
42 #define INVERSE 0x4 /* '^' invert the mask */
43
44 static int
match_class(char * s,char * prefix,uint_t m,int v)45 match_class(char *s, char *prefix, uint_t m, int v)
46 {
47 au_class_ent_t *p_class;
48
49 (void) strcat(s, prefix);
50 if (cacheauclass(&p_class, m) == 1) {
51 if (v == 0) {
52 (void) strncat(s, p_class->ac_name, AU_CLASS_NAME_MAX);
53 } else {
54 (void) strncat(s, p_class->ac_desc, AU_CLASS_DESC_MAX);
55 }
56 (void) strcat(s, ",");
57 return (0);
58 }
59 return (-1);
60 }
61
62 /*
63 * getauditflagschar() - convert bit flag to character string
64 *
65 * input: masks->am_success - audit on success
66 * masks->am_failure - audit on failure
67 * verbose - string format. 0 if short name; 1 if long name;
68 *
69 * output: auditstring - resultant audit string
70 *
71 * returns: 0 - entry read ok
72 * -1 - error
73 */
74
75 int
getauditflagschar(char * auditstring,au_mask_t * masks,int verbose)76 getauditflagschar(char *auditstring, au_mask_t *masks, int verbose)
77 {
78 char *prefix; /* +, -, or null */
79 unsigned int m; /* for masking with masks */
80 au_mask_t all; /* value for the string "all" */
81 int plus_all = 0; /* true if +all */
82 int minus_all = 0; /* true if -all */
83 int l;
84
85 /* initialize input buffer */
86 *auditstring = '\0';
87 /* no masks, no flags; we're outta here */
88 if ((masks->am_success == 0) && (masks->am_failure == 0)) {
89 if (match_class(auditstring, "", 0, verbose) != 0)
90 return (-1);
91 /* kludge to get rid of trailing comma */
92 l = strlen(auditstring) - 1;
93 if (auditstring[l] == ',')
94 auditstring[l] = '\0';
95 return (0);
96 }
97 /* Get the mask value for the string "all" */
98 all.am_success = 0;
99 all.am_failure = 0;
100 if (getauditflagsbin("all", &all) != 0)
101 return (-1);
102 if (all.am_success == masks->am_success) {
103 if (all.am_failure == masks->am_failure) {
104 (void) strcat(auditstring, "all");
105 return (0);
106 }
107 (void) strcat(auditstring, "+all,");
108 plus_all = 1;
109 } else if (all.am_failure == masks->am_failure) {
110 (void) strcat(auditstring, "-all,");
111 minus_all = 1;
112 }
113 for (m = (unsigned)0x80000000; m != 0; m >>= 1) {
114 if (m & masks->am_success & masks->am_failure)
115 prefix = plus_all ? "-" : (minus_all ? "+" : "");
116 else if (m & masks->am_success)
117 prefix = "+";
118 else if (m & masks->am_failure)
119 prefix = "-";
120 else
121 continue;
122 if (match_class(auditstring, prefix, m, verbose) != 0)
123 return (-1);
124 }
125 if (*(prefix = auditstring + strlen(auditstring) - 1) == ',')
126 *prefix = '\0';
127 return (0);
128
129 }
130
131 /*
132 * Audit flags:
133 *
134 * [+ | - | ^ | ^+ | ^-]<classname>{,[+ | - | ^ | ^+ | ^-]<classname>}*
135 *
136 * <classname>, add class mask to success and failure mask.
137 * +<classname>, add class mask only to success mask.
138 * -<classname>, add class mask only to failure mask.
139 * ^<classname>, remove class mask from success and failure mask.
140 * ^+<classname>, remove class mask from success mask.
141 * ^-<classname>, remove class mask from failure mask.
142 */
143
144 /*
145 * __chkflags - check if the audit flags are valid for this system
146 *
147 * Entry flags = audit flags string.
148 * cont = B_TRUE, continue parsing even if error.
149 * B_FALSE, return failure on error.
150 *
151 * Exit mask = audit mask as defined by flags.
152 *
153 * Return B_TRUE if no errors, or continue == B_TRUE.
154 * B_FALSE and if error != NULL, flags in error.
155 */
156
157 boolean_t
__chkflags(char * flags,au_mask_t * mask,boolean_t cont,char ** error)158 __chkflags(char *flags, au_mask_t *mask, boolean_t cont, char **error)
159 {
160 uint32_t prefix;
161 au_class_ent_t *class;
162 char name[AU_CLASS_NAME_MAX+1];
163 int i;
164
165 if (flags == NULL || mask == NULL) {
166 return (B_FALSE);
167 }
168
169 mask->am_success = 0;
170 mask->am_failure = 0;
171
172 while (*flags != '\0') {
173 prefix = (SUCCESS | FAILURE);
174
175 /* skip white space */
176 while (isspace(*flags)) {
177 flags++;
178 }
179
180 if (*flags == '\0') {
181 break;
182 }
183 if (error != NULL) {
184 /* save error pointer */
185 *error = flags;
186 }
187
188 /* get the prefix */
189 if (*flags == '+') {
190 flags++;
191 prefix ^= FAILURE;
192 } else if (*flags == '-') {
193 flags++;
194 prefix ^= SUCCESS;
195 } else if (*flags == '^') {
196 flags++;
197 prefix |= INVERSE;
198 if (*flags == '+') {
199 flags++;
200 prefix ^= FAILURE;
201 } else if (*flags == '-') {
202 flags++;
203 prefix ^= SUCCESS;
204 }
205 }
206
207 /* get class name */
208
209 for (i = 0; (i < sizeof (name) - 1) &&
210 !(*flags == '\0' || *flags == ','); i++) {
211 name[i] = *flags++;
212 }
213 name[i++] = '\0';
214 if (*flags == ',') {
215 /* skip comma (',') */
216 flags++;
217 }
218 if (cacheauclassnam(&class, name) != 1) {
219 if (!cont) {
220 return (B_FALSE);
221 } else {
222 char msg[512];
223
224 (void) snprintf(msg, sizeof (msg), "invalid "
225 "audit flag %s", name);
226 adt_write_syslog(msg, EINVAL);
227 }
228 } else {
229 /* add class mask */
230
231 if ((prefix & (INVERSE | SUCCESS)) == SUCCESS) {
232 mask->am_success |= class->ac_class;
233 } else if ((prefix & (INVERSE | SUCCESS)) ==
234 (INVERSE | SUCCESS)) {
235 mask->am_success &= ~(class->ac_class);
236 }
237 if ((prefix & (INVERSE | FAILURE)) == FAILURE) {
238 mask->am_failure |= class->ac_class;
239 } else if ((prefix & (INVERSE | FAILURE)) ==
240 (INVERSE | FAILURE)) {
241 mask->am_failure &= ~(class->ac_class);
242 }
243 }
244 }
245
246 return (B_TRUE);
247 }
248
249 /*
250 * getauditflagsbin() - converts character string to success and
251 * failure bit masks
252 *
253 * input: auditstring - audit string
254 *
255 * output: masks->am_success - audit on success
256 * masks->am_failure - audit on failure
257 *
258 * returns: 0 - ok
259 * -1 - error - string or mask NULL.
260 */
261
262 int
getauditflagsbin(char * auditstring,au_mask_t * masks)263 getauditflagsbin(char *auditstring, au_mask_t *masks)
264 {
265 if (__chkflags(auditstring, masks, B_TRUE, NULL)) {
266 return (0);
267 }
268 return (-1);
269 }
270