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 #pragma ident "%Z%%M% %I% %E% SMI" 22 23 #ifndef lint 24 static char sccsid[] = "%Z%%M% %I% %E% SMI"; 25 #endif 26 27 /* 28 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 29 * Use is subject to license terms. 30 */ 31 32 /* 33 * Interfaces to audit_event(5) (/etc/security/audit_event) 34 */ 35 36 /* 37 * This routine is obsolete. I have removed its inclusion by removing 38 * the .o from the makefile. Please use cacheauevent() or any of the 39 * getauev* routines. 40 */ 41 42 #include <sys/types.h> 43 #include <limits.h> 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <bsm/audit.h> 48 #include <bsm/libbsm.h> 49 #include <synch.h> 50 51 /* 52 * Macros to produce a quoted string containing the value of a 53 * preprocessor macro. For example, if SIZE is defined to be 256, 54 * VAL2STR(SIZE) is "256". This is used to construct format 55 * strings for scanf-family functions below. 56 */ 57 #define QUOTE(x) #x 58 #define VAL2STR(x) QUOTE(x) 59 60 static au_class_t flagstohex(char *); 61 62 static char au_event_fname[PATH_MAX] = AUDITEVENTFILE; 63 static FILE *au_event_file = (FILE *)0; 64 static mutex_t mutex_eventfile = DEFAULTMUTEX; 65 static mutex_t mutex_eventcache = DEFAULTMUTEX; 66 67 extern int _mutex_lock(mutex_t *); 68 extern int _mutex_unlock(mutex_t *); 69 70 int 71 #ifdef __STDC__ 72 setaueventfile(char *fname) 73 #else 74 setaueventfile(fname) 75 char *fname; 76 #endif 77 { 78 _mutex_lock(&mutex_eventfile); 79 if (fname) { 80 (void) strcpy(au_event_fname, fname); 81 } 82 _mutex_unlock(&mutex_eventfile); 83 return (0); 84 } 85 86 87 void 88 setauevent() 89 { 90 _mutex_lock(&mutex_eventfile); 91 if (au_event_file) { 92 (void) fseek(au_event_file, 0L, 0); 93 } 94 _mutex_unlock(&mutex_eventfile); 95 } 96 97 98 void 99 endauevent() 100 { 101 _mutex_lock(&mutex_eventfile); 102 if (au_event_file) { 103 (void) fclose(au_event_file); 104 au_event_file = (FILE *)0; 105 } 106 _mutex_unlock(&mutex_eventfile); 107 } 108 109 au_event_ent_t * 110 getauevent() 111 { 112 static au_event_ent_t au_event_entry; 113 static char ename[AU_EVENT_NAME_MAX]; 114 static char edesc[AU_EVENT_DESC_MAX]; 115 116 /* initialize au_event_entry structure */ 117 au_event_entry.ae_name = ename; 118 au_event_entry.ae_desc = edesc; 119 120 return (getauevent_r(&au_event_entry)); 121 } 122 123 au_event_ent_t * 124 getauevent_r(au_event_entry) 125 au_event_ent_t *au_event_entry; 126 { 127 int i, error = 0, found = 0; 128 char *s, input[AU_EVENT_LINE_MAX]; 129 char trim_buf[AU_EVENT_NAME_MAX+1]; 130 131 /* open audit event file if it isn't already */ 132 _mutex_lock(&mutex_eventfile); 133 if (!au_event_file) 134 if (!(au_event_file = fopen(au_event_fname, "rF"))) { 135 _mutex_unlock(&mutex_eventfile); 136 return ((au_event_ent_t *)0); 137 } 138 139 while (fgets(input, AU_EVENT_LINE_MAX, au_event_file)) { 140 if (input[0] != '#') { 141 s = input + strspn(input, " \t\r\n"); 142 if ((*s == '\0') || (*s == '#')) { 143 continue; 144 } 145 found = 1; 146 s = input; 147 148 /* parse number */ 149 i = strcspn(s, ":"); 150 s[i] = '\0'; 151 (void) sscanf(s, "%hd", &au_event_entry->ae_number); 152 s = &s[i+1]; 153 154 /* parse event name */ 155 i = strcspn(s, ":"); 156 s[i] = '\0'; 157 (void) sscanf(s, "%" VAL2STR(AU_EVENT_NAME_MAX) "s", 158 trim_buf); 159 (void) strncpy(au_event_entry->ae_name, trim_buf, 160 AU_EVENT_NAME_MAX); 161 s = &s[i+1]; 162 163 /* parse event description */ 164 i = strcspn(s, ":"); 165 s[i] = '\0'; 166 (void) strncpy(au_event_entry->ae_desc, s, 167 AU_EVENT_DESC_MAX); 168 s = &s[i+1]; 169 170 /* parse class */ 171 i = strcspn(s, "\n\0"); 172 s[i] = '\0'; 173 (void) sscanf(s, "%" VAL2STR(AU_EVENT_NAME_MAX) "s", 174 trim_buf); 175 au_event_entry->ae_class = flagstohex(trim_buf); 176 177 break; 178 } 179 } 180 _mutex_unlock(&mutex_eventfile); 181 182 if (!error && found) { 183 return (au_event_entry); 184 } else { 185 return ((au_event_ent_t *)0); 186 } 187 } 188 189 190 au_event_ent_t * 191 #ifdef __STDC__ 192 getauevnam(char *name) 193 #else 194 getauevnam(name) 195 char *name; 196 #endif 197 { 198 static au_event_ent_t au_event_entry; 199 static char ename[AU_EVENT_NAME_MAX]; 200 static char edesc[AU_EVENT_DESC_MAX]; 201 202 /* initialize au_event_entry structure */ 203 au_event_entry.ae_name = ename; 204 au_event_entry.ae_desc = edesc; 205 206 return (getauevnam_r(&au_event_entry, name)); 207 } 208 209 au_event_ent_t * 210 #ifdef __STDC__ 211 getauevnam_r(au_event_ent_t *e, char *name) 212 #else 213 getauevnam_r(e, name) 214 au_event_ent_t &e; 215 char *name; 216 #endif 217 { 218 setauevent(); 219 while (getauevent_r(e) != NULL) { 220 if (strcmp(e->ae_name, name) == 0) { 221 endauevent(); 222 return (e); 223 } 224 } 225 endauevent(); 226 return ((au_event_ent_t *)NULL); 227 } 228 229 au_event_ent_t * 230 #ifdef __STDC__ 231 getauevnum_r(au_event_ent_t *e, au_event_t event_number) 232 #else 233 getauevnum_r(e, event_number) 234 au_event_ent_t *e; 235 au_event_t event_number; 236 #endif 237 { 238 setauevent(); 239 while (getauevent_r(e) != NULL) { 240 if (e->ae_number == event_number) { 241 endauevent(); 242 return (e); 243 } 244 } 245 endauevent(); 246 return ((au_event_ent_t *)NULL); 247 } 248 249 au_event_ent_t * 250 #ifdef __STDC__ 251 getauevnum(au_event_t event_number) 252 #else 253 getauevnum(event_number) 254 au_event_t event_number; 255 #endif 256 { 257 static au_event_ent_t e; 258 static char ename[AU_EVENT_NAME_MAX]; 259 static char edesc[AU_EVENT_DESC_MAX]; 260 261 /* initialize au_event_entry structure */ 262 e.ae_name = ename; 263 e.ae_desc = edesc; 264 265 return (getauevnum_r(&e, event_number)); 266 } 267 268 au_event_t 269 #ifdef __STDC__ 270 getauevnonam(char *event_name) 271 #else 272 getauevnonam(event_name) 273 char *event_name; 274 #endif 275 { 276 au_event_ent_t e; 277 char ename[AU_EVENT_NAME_MAX]; 278 char edesc[AU_EVENT_DESC_MAX]; 279 280 /* initialize au_event_entry structure */ 281 e.ae_name = ename; 282 e.ae_desc = edesc; 283 284 if (getauevnam_r(&e, event_name) == (au_event_ent_t *)0) { 285 return (-1); 286 } 287 return (e.ae_number); 288 } 289 290 /* 291 * cacheauevent: 292 * Read the entire audit_event file into memory. 293 * Set a pointer to the requested entry in the cache 294 * or a pointer to an invalid entry if the event number 295 * is not known. 296 * 297 * Return < 0, if error. 298 * Return 0, if event number not in cache. 299 * Return 1, if event number is in cache. 300 */ 301 302 int 303 #ifdef __STDC__ 304 cacheauevent(au_event_ent_t **result, au_event_t event_number) 305 #else 306 cacheauevent(result, event_number) 307 au_event_ent_t **result; /* set this pointer to an entry in the cache */ 308 au_event_t event_number; /* request this event number */ 309 #endif 310 { 311 static ushort_t max; /* the highest event number in the file */ 312 static ushort_t min; /* the lowest event number in the file */ 313 static int invalid; /* 1+index of the highest event number */ 314 static au_event_ent_t **index_tbl; 315 static au_event_ent_t **p_tbl; 316 static int called_once = 0; 317 318 char line[AU_EVENT_LINE_MAX]; 319 int lines = 0; 320 FILE *fp; 321 au_event_ent_t *p_event; 322 int i, size; 323 int hit = 0; 324 char *s; 325 326 _mutex_lock(&mutex_eventcache); 327 if (called_once == 0) { 328 329 /* Count number of lines in the events file */ 330 if ((fp = fopen(au_event_fname, "rF")) == NULL) { 331 _mutex_unlock(&mutex_eventcache); 332 return (-1); 333 } 334 while (fgets(line, AU_EVENT_LINE_MAX, fp) != NULL) { 335 s = line + strspn(line, " \t\r\n"); 336 if ((*s == '\0') || (*s == '#')) { 337 continue; 338 } 339 lines++; 340 } 341 (void) fclose(fp); 342 size = lines; 343 344 /* 345 * Make an array in which each element in an entry in the 346 * events file. Make the next to last element an invalid 347 * event. Make the last element a NULL pointer. 348 */ 349 350 p_tbl = calloc(lines + 1, sizeof (au_event_ent_t)); 351 if (p_tbl == NULL) { 352 _mutex_unlock(&mutex_eventcache); 353 return (-2); 354 } 355 lines = 0; 356 max = 0; 357 min = 65535; 358 setauevent(); 359 while ((p_event = getauevent()) != NULL) { 360 p_tbl[lines] = (au_event_ent_t *) 361 malloc(sizeof (au_event_ent_t)); 362 if (p_tbl[lines] == NULL) { 363 _mutex_unlock(&mutex_eventcache); 364 return (-3); 365 } 366 p_tbl[lines]->ae_number = p_event->ae_number; 367 p_tbl[lines]->ae_name = strdup(p_event->ae_name); 368 p_tbl[lines]->ae_desc = strdup(p_event->ae_desc); 369 p_tbl[lines]->ae_class = p_event->ae_class; 370 #ifdef DEBUG2 371 printevent(p_tbl[lines]); 372 #endif 373 if ((ushort_t)p_event->ae_number > max) { 374 max = p_event->ae_number; 375 } 376 if ((ushort_t)p_event->ae_number < min) { 377 min = p_event->ae_number; 378 } 379 lines++; 380 } 381 endauevent(); 382 invalid = lines; 383 p_tbl[invalid] = (au_event_ent_t *) 384 malloc(sizeof (au_event_ent_t)); 385 if (p_tbl[invalid] == NULL) { 386 _mutex_unlock(&mutex_eventcache); 387 return (-4); 388 } 389 p_tbl[invalid]->ae_number = -1; 390 p_tbl[invalid]->ae_name = "invalid event number"; 391 p_tbl[invalid]->ae_desc = p_tbl[invalid]->ae_name; 392 p_tbl[invalid]->ae_class = (au_class_t)-1; 393 394 #ifdef DEBUG2 395 for (i = 0; i < size; i++) { 396 printf("%d:%s:%s:%d\n", p_tbl[i]->ae_number, 397 p_tbl[i]->ae_name, p_tbl[i]->ae_desc, 398 p_tbl[i]->ae_class); 399 } 400 #endif 401 402 /* get space for the index_tbl */ 403 index_tbl = calloc(max+1, sizeof (au_event_ent_t *)); 404 if (index_tbl == NULL) { 405 _mutex_unlock(&mutex_eventcache); 406 return (-5); 407 } 408 409 /* intialize the index_tbl to the invalid event number */ 410 for (i = 0; (ushort_t)i < max; i++) { 411 index_tbl[i] = p_tbl[invalid]; 412 } 413 414 /* point each index_tbl element at the corresponding event */ 415 for (i = 0; i < size; i++) { 416 index_tbl[(ushort_t)p_tbl[i]->ae_number] = p_tbl[i]; 417 } 418 419 called_once = 1; 420 421 } 422 423 if ((ushort_t)event_number > max || (ushort_t)event_number < min) { 424 *result = index_tbl[invalid]; 425 } else { 426 *result = index_tbl[(ushort_t)event_number]; 427 hit = 1; 428 } 429 _mutex_unlock(&mutex_eventcache); 430 return (hit); 431 } 432 433 434 static au_class_t 435 flagstohex(char *flags) 436 { 437 au_class_ent_t *p_class; 438 unsigned int hex = 0; 439 char *comma = ","; 440 char *s; 441 char *last; 442 443 s = strtok_r(flags, comma, &last); 444 while (s != NULL) { 445 (void) cacheauclassnam(&p_class, s); 446 hex |= p_class->ac_class; 447 s = strtok_r(NULL, comma, &last); 448 } 449 return (hex); 450 } 451 452 453 #ifdef DEBUG2 454 void 455 printevent(p_event) 456 au_event_ent_t *p_event; 457 { 458 printf("%d:%s:%s:%d\n", p_event->ae_number, p_event->ae_name, 459 p_event->ae_desc, p_event->ae_class); 460 fflush(stdout); 461 } 462 463 464 #endif 465