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 1992 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <sys/label.h>
33 #include <sys/audit.h>
34 #include <auevents.h>
35
36 #define ON 1
37 #define OK 0
38 #define OFF -1
39 #define COMMA ','
40 #define COMMASTR ","
41
42 #define COMMON 0
43 #define SUCCESS 1
44 #define FAILURE 2
45
46 #define MAXFLDLEN 25
47 #define MAXSTRLEN 360
48 #define MAXEVENT 11
49
50 /* GLOBALS */
51
52 static int length;
53 static int pos = 0;
54
55 struct list {
56 short count;
57 short on[MAXEVENT+1];
58 short off;
59 };
60 typedef struct list list_t;
61
62 struct exception {
63 short type;
64 short exception;
65 };
66 typedef struct exception except_t;
67
68 static int stringcopy(char *, char *, int);
69
70 /*
71 * getauditflagschar() - convert bit flag to character string
72 *
73 * input: masks->as_success - audit on success
74 * masks->as_failure - audit on failure
75 * verbose - string format. 0 if short name; 1 if long name;
76 *
77 * output: auditstring - resultant audit string
78 *
79 * returns: 0 - entry read ok
80 * -1 - error
81 */
82
83 int
getauditflagschar(char * auditstring,audit_state_t * masks,int verbose)84 getauditflagschar(char *auditstring, audit_state_t *masks, int verbose)
85 {
86 int i, j, k, mask_num;
87 int list = -1, retstat = 0;
88 int except_list[3];
89 char *prefix = " ";
90 except_t except[2];
91 list_t lists[3];
92
93 /*
94 * initialize input buffer
95 */
96 strcpy(auditstring, "");
97 /*
98 * initialize lists struct
99 */
100 for (mask_num = COMMON; mask_num <= FAILURE; mask_num++) {
101 lists[mask_num].count = 0;
102 lists[mask_num].off = -1;
103 for (i=0;i<MAXEVENT+1;i++)
104 lists[mask_num].on[i] = -1;
105 }
106 /*
107 * initialize exception lists
108 */
109 for (i = 0; i < 2; i++) {
110 except[i].type = -1;
111 except[i].exception = -1;
112 }
113
114 for (i = 0; i < 3; i++)
115 except_list[i] = 0;
116
117 /*
118 * set length global
119 */
120 length = verbose;
121 pos = 0;
122
123 /*
124 * find turned-on events - if on, store index of event
125 * in one of the three event lists, common, success, failure.
126 */
127 for ( i = 0; i < MAXEVENT; i++) {
128 if (((event_class[i].event_mask & masks->as_success) > 0) ||
129 ((event_class[i].event_mask & masks->as_failure) > 0)) {
130
131 /*
132 * check for events in common
133 */
134 if (((event_class[i].event_mask & masks->as_success) >
135 0) &&
136 ((event_class[i].event_mask & masks->as_failure) > 0))
137 lists[COMMON].on[lists[COMMON].count++] = i;
138
139 /*
140 * check for success events
141 */
142 if ((event_class[i].event_mask & masks->as_success) > 0)
143 lists[SUCCESS].on[lists[SUCCESS].count++] = i;
144 else {
145 except_list[SUCCESS]++;
146 if (lists[SUCCESS].off == -1)
147 lists[SUCCESS].off = i;
148 }
149 /*
150 * check for failure events
151 */
152 if ((event_class[i].event_mask & masks->as_failure) > 0)
153 lists[FAILURE].on[lists[FAILURE].count++] = i;
154 else {
155 except_list[FAILURE]++;
156 if (lists[FAILURE].off == -1)
157 lists[FAILURE].off = i;
158 }
159 } else {
160 except_list[COMMON]++;
161 if (lists[COMMON].off == -1)
162 lists[COMMON].off = i;
163 }
164 }
165 /*
166 * check for all set or all-1 set - output all and common exceptions.
167 * the all or common state is exclusive; only one of the
168 * three, (+-)all, allowed
169 */
170 /*
171 * no exceptions
172 */
173 if (lists[COMMON].count >= MAXEVENT-2) {
174 if (lists[COMMON].count == MAXEVENT)
175 list = COMMON;
176
177 /*
178 * one exception
179 */
180 else if (lists[COMMON].count == MAXEVENT-1) {
181 for (i=COMMON;i<=FAILURE && (list == -1);i++) {
182 if (except_list[i] == 1) {
183 list = COMMON;
184 except[0].type = i;
185 except[0].exception = lists[i].off;
186 }
187 }
188 }
189 /*
190 * two exceptions
191 */
192 else if (lists[COMMON].count == MAXEVENT-2) {
193 if (except_list[COMMON] == 1) {
194 list = COMMON;
195 except[0].type = COMMON;
196 except[0].exception = lists[COMMON].off;
197 for (i=SUCCESS;i<=FAILURE;i++) {
198 if (except_list[i] == 1) {
199 except[1].type = i;
200 except[1].exception = lists[i].off;
201 }
202 }
203
204 } else if (except_list[COMMON] == 0) {
205 for (i=SUCCESS,j=0;i<=FAILURE;i++) {
206 if (except_list[i] == 1) {
207 list = COMMON;
208 except[j].type = i;
209 except[j++].exception = lists[i].off;
210 }
211 }
212 }
213 }
214 } else {
215 /*
216 * check for +all or -all
217 */
218 for (i=SUCCESS,j=0;i<=FAILURE;i++) {
219 if (lists[i].count >= MAXEVENT-1) {
220 list = i;
221 except[j].type = i;
222 if (lists[i].count != MAXEVENT) {
223 if (lists[i].off != -1)
224 except[j++].exception =
225 lists[i].off;
226 else
227 except[j++].exception =
228 lists[COMMON].off;
229 }
230 }
231 }
232 }
233 /*
234 * output all and exceptions
235 */
236 if (list != -1) {
237 if(list==SUCCESS) {
238 if ((stringcopy(auditstring, "+", 0)) == -1)
239 retstat = -1;
240 }
241 if(list==FAILURE) {
242 if ((stringcopy(auditstring, "-", 0)) == -1)
243 retstat = -1;
244 }
245
246 if (retstat == 0) {
247 if (length) {
248 if
249 ((stringcopy(auditstring,event_class[11].event_lname,1)) == -1)
250 retstat = -1;
251 } else
252 if ((stringcopy(auditstring, event_class[11].event_sname,1)) == -1)
253 retstat = -1;
254 }
255
256 if (retstat == 0) {
257 /*
258 * output exceptions
259 */
260 for (i=0;i<2 && except[i].exception != -1; i++) {
261 if ((stringcopy(auditstring, "^", 0)) == -1)
262 retstat = -1;
263 if(except[i].type==SUCCESS) {
264 if ((stringcopy(auditstring, "+", 0)) == -1)
265 retstat = -1;
266 }
267 if (except[i].type==FAILURE) {
268 if ((stringcopy(auditstring, "-", 0)) == -1)
269 retstat = -1;
270 }
271 if (length == 1 && retstat == 0) {
272 if ((stringcopy(auditstring,
273 event_class[except[i].exception].event_lname, 1))==-1)
274 retstat = -1;
275 } else if (retstat == 0) {
276 if ((stringcopy(auditstring,
277 event_class[except[i].exception].event_sname, 1))==-1)
278 retstat = -1;
279 }
280 }
281 }
282 } /* end of " all " processing */
283
284 /*
285 * process common events if no "all" was output
286 */
287 if (list == -1 && (lists[COMMON].count > 0) && retstat == 0) {
288 /*
289 * output common events first
290 */
291 for (j=0;j<lists[COMMON].count;j++) {
292 if (length == 1) {
293 if ((stringcopy(auditstring,
294 event_class[lists[COMMON].on[j]].event_lname, 1)) == -1)
295 retstat = -1;
296 } else if ((stringcopy(auditstring,
297 event_class[lists[COMMON].on[j]].event_sname, 1)) == -1)
298 retstat = -1;
299 }
300 /*
301 * remove common events from individual lists
302 */
303 if (retstat == 0) {
304 for (i=SUCCESS;i<=FAILURE;i++) {
305 for(j=0;j<lists[COMMON].count;j++) {
306 for(k=0;k < lists[i].count;k++) {
307 if (lists[COMMON].on[j] ==
308 lists[i].on[k])
309 lists[i].on[k] = -1;
310 }
311 }
312 }
313 }
314 }
315
316 /*
317 * start processing individual event flags in success
318 * and failure lists
319 */
320 if (list != COMMON && retstat == 0) {
321 for (i=SUCCESS;i<=FAILURE;i++) {
322 if(list != i) {
323 if (i==SUCCESS) strcpy(prefix, "+");
324 if (i==FAILURE) strcpy(prefix, "-");
325 for (j=0;j<MAXEVENT && j<lists[i].count;j++) {
326 if (lists[i].on[j] != -1) {
327 if ((stringcopy(auditstring, prefix, 0)) == -1)
328 retstat = -1;
329 if (length == 1 &&
330 retstat == 0) {
331 if ((stringcopy(auditstring,
332 event_class[lists[i].on[j]].event_lname, 1))==-1)
333 retstat = -1;
334 } else if (retstat == 0) {
335 if ((stringcopy(auditstring,
336 event_class[lists[i].on[j]].event_sname, 1))==-1)
337 retstat = -1;
338 }
339 }
340 }
341 }
342 }
343 }
344 if ((stringcopy(auditstring, "\0", 2)) == -1)
345 retstat = -1;
346
347 return (retstat);
348 }
349
350 static int
stringcopy(char * auditstring,char * event,int flag)351 stringcopy(char *auditstring, char *event,
352 int flag) /* if set, output comma after event */
353 {
354 int retstat = 0;
355
356 /*
357 * check size
358 */
359 if (pos >= MAXSTRLEN) {
360 fprintf(stderr,"getauditflagschar: Inputted buffer too small.\n");
361 retstat = -1;
362 } else if (flag != 2) {
363 strcpy(auditstring+pos, event);
364 pos += strlen(event);
365 if(flag) {
366 strcpy(auditstring+pos, COMMASTR);
367 pos += strlen(COMMASTR);
368 }
369 } else {
370 /*
371 * add null terminator only
372 */
373 if (pos)
374 strcpy(auditstring+(pos-1), event);
375
376 }
377 return (retstat);
378 }
379
380 /*
381 * getauditflagsbin() - converts character string to success and
382 * failure bit masks
383 *
384 * input: auditstring - audit string
385 * cnt - number of elements in the masks array
386 *
387 * output: masks->as_success - audit on success
388 * masks->as_failure - audit on failure
389 *
390 * returns: 0 - ok
391 * -1 - error - string contains characters which do
392 * not match event flag names
393 */
394
395 int
getauditflagsbin(char * auditstring,audit_state_t * masks)396 getauditflagsbin(char *auditstring, audit_state_t *masks)
397 {
398 int i, gotone, done = 0, invert = 0, tryagain;
399 int retstat = 0, succ_event, fail_event;
400 char *ptr, tmp_buff[MAXFLDLEN];
401
402 /*
403 * process character string
404 */
405 do {
406 gotone = 0;
407 /*
408 * read through string storing chars. until a comma
409 */
410 for (ptr=tmp_buff; !gotone;) {
411 if(*auditstring!=COMMA && *auditstring!='\0' &&
412 *auditstring!='\n' && *auditstring!=' ')
413 *ptr++ = *auditstring++;
414 else if (*auditstring == ' ')
415 *auditstring++;
416 else {
417 if (*auditstring == '\0' ||
418 *auditstring == '\n') {
419 done = 1;
420 if (ptr == tmp_buff)
421 done = 2;
422 }
423 gotone = 1;
424 }
425 }
426 /*
427 * process audit state
428 */
429 if(gotone && done != 2) {
430 if(!done) auditstring++;
431 *ptr++ = '\0';
432 ptr = tmp_buff;
433 gotone = 0;
434 succ_event = ON;
435 fail_event = ON;
436 tryagain = 1;
437 invert = 0;
438
439 /*
440 * get flags
441 */
442 do {
443 switch (*ptr++) {
444 case '^':
445 invert = 1;
446 succ_event = OFF;
447 fail_event = OFF;
448 break;
449 case '+':
450 if (invert)
451 fail_event = OK;
452 else {
453 succ_event = ON;
454 fail_event = OK;
455 }
456 break;
457 case '-':
458 if (invert)
459 succ_event = OK;
460 else {
461 fail_event = ON;
462 succ_event = OK;
463 }
464 break;
465 default:
466 tryagain = 0;
467 ptr--;
468 break;
469 }
470 } while(tryagain);
471
472 /* add audit state to mask */
473 for (i=0;i<MAXEVENT+1 && !gotone;i++) {
474 if ((!(strcmp(ptr, event_class[i].event_sname))) ||
475 (!(strcmp(ptr, event_class[i].event_lname)))) {
476 if (succ_event == ON)
477 masks->as_success |= event_class[i].event_mask;
478 else if (succ_event == OFF)
479 masks->as_success &= ~(event_class[i].event_mask);
480 if (fail_event == ON)
481 masks->as_failure |= event_class[i].event_mask;
482 else if (fail_event == OFF)
483 masks->as_failure &= ~(event_class[i].event_mask);
484 gotone = 1;
485 }
486 }
487 if(!gotone) {
488 retstat = -1;
489 done = 1;
490 }
491 }
492 } while (!done);
493
494 return (retstat);
495 }
496