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