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 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 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 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