1 /*- 2 * Copyright (c) 2004 Apple Inc. 3 * Copyright (c) 2006 Robert N. M. Watson 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Inc. ("Apple") nor the names of 15 * its contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR 22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 * 30 * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_event.c#17 $ 31 */ 32 33 #include <config/config.h> 34 35 #include <bsm/libbsm.h> 36 37 #include <string.h> 38 #ifdef HAVE_PTHREAD_MUTEX_LOCK 39 #include <pthread.h> 40 #endif 41 #include <stdio.h> 42 #include <stdlib.h> 43 44 #ifndef HAVE_STRLCPY 45 #include <compat/strlcpy.h> 46 #endif 47 48 49 /* 50 * Parse the contents of the audit_event file to return 51 * au_event_ent entries 52 */ 53 static FILE *fp = NULL; 54 static char linestr[AU_LINE_MAX]; 55 static const char *eventdelim = ":"; 56 57 #ifdef HAVE_PTHREAD_MUTEX_LOCK 58 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 59 #endif 60 61 /* 62 * Parse one line from the audit_event file into the au_event_ent structure. 63 */ 64 static struct au_event_ent * 65 eventfromstr(char *str, struct au_event_ent *e) 66 { 67 char *evno, *evname, *evdesc, *evclass; 68 struct au_mask evmask; 69 char *last; 70 71 evno = strtok_r(str, eventdelim, &last); 72 evname = strtok_r(NULL, eventdelim, &last); 73 evdesc = strtok_r(NULL, eventdelim, &last); 74 evclass = strtok_r(NULL, eventdelim, &last); 75 76 if ((evno == NULL) || (evname == NULL)) 77 return (NULL); 78 79 if (strlen(evname) >= AU_EVENT_NAME_MAX) 80 return (NULL); 81 82 strlcpy(e->ae_name, evname, AU_EVENT_NAME_MAX); 83 if (evdesc != NULL) { 84 if (strlen(evdesc) >= AU_EVENT_DESC_MAX) 85 return (NULL); 86 strlcpy(e->ae_desc, evdesc, AU_EVENT_DESC_MAX); 87 } else 88 strlcpy(e->ae_desc, "", AU_EVENT_DESC_MAX); 89 90 e->ae_number = atoi(evno); 91 92 /* 93 * Find out the mask that corresponds to the given list of classes. 94 */ 95 if (evclass != NULL) { 96 if (getauditflagsbin(evclass, &evmask) != 0) 97 e->ae_class = 0; 98 else 99 e->ae_class = evmask.am_success; 100 } else 101 e->ae_class = 0; 102 103 return (e); 104 } 105 106 /* 107 * Rewind the audit_event file. 108 */ 109 static void 110 setauevent_locked(void) 111 { 112 113 if (fp != NULL) 114 fseek(fp, 0, SEEK_SET); 115 } 116 117 void 118 setauevent(void) 119 { 120 121 #ifdef HAVE_PTHREAD_MUTEX_LOCK 122 pthread_mutex_lock(&mutex); 123 #endif 124 setauevent_locked(); 125 #ifdef HAVE_PTHREAD_MUTEX_LOCK 126 pthread_mutex_unlock(&mutex); 127 #endif 128 } 129 130 /* 131 * Close the open file pointers. 132 */ 133 void 134 endauevent(void) 135 { 136 137 #ifdef HAVE_PTHREAD_MUTEX_LOCK 138 pthread_mutex_lock(&mutex); 139 #endif 140 if (fp != NULL) { 141 fclose(fp); 142 fp = NULL; 143 } 144 #ifdef HAVE_PTHREAD_MUTEX_LOCK 145 pthread_mutex_unlock(&mutex); 146 #endif 147 } 148 149 /* 150 * Enumerate the au_event_ent entries. 151 */ 152 static struct au_event_ent * 153 getauevent_r_locked(struct au_event_ent *e) 154 { 155 char *nl; 156 157 if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL)) 158 return (NULL); 159 160 while (1) { 161 if (fgets(linestr, AU_LINE_MAX, fp) == NULL) 162 return (NULL); 163 164 /* Remove new lines. */ 165 if ((nl = strrchr(linestr, '\n')) != NULL) 166 *nl = '\0'; 167 168 /* Skip comments. */ 169 if (linestr[0] == '#') 170 continue; 171 172 /* Get the next event structure. */ 173 if (eventfromstr(linestr, e) == NULL) 174 return (NULL); 175 break; 176 } 177 178 return (e); 179 } 180 181 struct au_event_ent * 182 getauevent_r(struct au_event_ent *e) 183 { 184 struct au_event_ent *ep; 185 186 #ifdef HAVE_PTHREAD_MUTEX_LOCK 187 pthread_mutex_lock(&mutex); 188 #endif 189 ep = getauevent_r_locked(e); 190 #ifdef HAVE_PTHREAD_MUTEX_LOCK 191 pthread_mutex_unlock(&mutex); 192 #endif 193 return (ep); 194 } 195 196 struct au_event_ent * 197 getauevent(void) 198 { 199 static char event_ent_name[AU_EVENT_NAME_MAX]; 200 static char event_ent_desc[AU_EVENT_DESC_MAX]; 201 static struct au_event_ent e; 202 203 bzero(&e, sizeof(e)); 204 bzero(event_ent_name, sizeof(event_ent_name)); 205 bzero(event_ent_desc, sizeof(event_ent_desc)); 206 e.ae_name = event_ent_name; 207 e.ae_desc = event_ent_desc; 208 return (getauevent_r(&e)); 209 } 210 211 /* 212 * Search for an audit event structure having the given event name. 213 * 214 * XXXRW: Why accept NULL name? 215 */ 216 static struct au_event_ent * 217 getauevnam_r_locked(struct au_event_ent *e, const char *name) 218 { 219 char *nl; 220 221 if (name == NULL) 222 return (NULL); 223 224 /* Rewind to beginning of the file. */ 225 setauevent_locked(); 226 227 if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL)) 228 return (NULL); 229 230 while (fgets(linestr, AU_LINE_MAX, fp) != NULL) { 231 /* Remove new lines. */ 232 if ((nl = strrchr(linestr, '\n')) != NULL) 233 *nl = '\0'; 234 235 if (eventfromstr(linestr, e) != NULL) { 236 if (strcmp(name, e->ae_name) == 0) 237 return (e); 238 } 239 } 240 241 return (NULL); 242 } 243 244 struct au_event_ent * 245 getauevnam_r(struct au_event_ent *e, const char *name) 246 { 247 struct au_event_ent *ep; 248 249 #ifdef HAVE_PTHREAD_MUTEX_LOCK 250 pthread_mutex_lock(&mutex); 251 #endif 252 ep = getauevnam_r_locked(e, name); 253 #ifdef HAVE_PTHREAD_MUTEX_LOCK 254 pthread_mutex_unlock(&mutex); 255 #endif 256 return (ep); 257 } 258 259 struct au_event_ent * 260 getauevnam(const char *name) 261 { 262 static char event_ent_name[AU_EVENT_NAME_MAX]; 263 static char event_ent_desc[AU_EVENT_DESC_MAX]; 264 static struct au_event_ent e; 265 266 bzero(&e, sizeof(e)); 267 bzero(event_ent_name, sizeof(event_ent_name)); 268 bzero(event_ent_desc, sizeof(event_ent_desc)); 269 e.ae_name = event_ent_name; 270 e.ae_desc = event_ent_desc; 271 return (getauevnam_r(&e, name)); 272 } 273 274 /* 275 * Search for an audit event structure having the given event number. 276 */ 277 static struct au_event_ent * 278 getauevnum_r_locked(struct au_event_ent *e, au_event_t event_number) 279 { 280 char *nl; 281 282 /* Rewind to beginning of the file. */ 283 setauevent_locked(); 284 285 if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL)) 286 return (NULL); 287 288 while (fgets(linestr, AU_LINE_MAX, fp) != NULL) { 289 /* Remove new lines. */ 290 if ((nl = strrchr(linestr, '\n')) != NULL) 291 *nl = '\0'; 292 293 if (eventfromstr(linestr, e) != NULL) { 294 if (event_number == e->ae_number) 295 return (e); 296 } 297 } 298 299 return (NULL); 300 } 301 302 struct au_event_ent * 303 getauevnum_r(struct au_event_ent *e, au_event_t event_number) 304 { 305 struct au_event_ent *ep; 306 307 #ifdef HAVE_PTHREAD_MUTEX_LOCK 308 pthread_mutex_lock(&mutex); 309 #endif 310 ep = getauevnum_r_locked(e, event_number); 311 #ifdef HAVE_PTHREAD_MUTEX_LOCK 312 pthread_mutex_unlock(&mutex); 313 #endif 314 return (ep); 315 } 316 317 struct au_event_ent * 318 getauevnum(au_event_t event_number) 319 { 320 static char event_ent_name[AU_EVENT_NAME_MAX]; 321 static char event_ent_desc[AU_EVENT_DESC_MAX]; 322 static struct au_event_ent e; 323 324 bzero(&e, sizeof(e)); 325 bzero(event_ent_name, sizeof(event_ent_name)); 326 bzero(event_ent_desc, sizeof(event_ent_desc)); 327 e.ae_name = event_ent_name; 328 e.ae_desc = event_ent_desc; 329 return (getauevnum_r(&e, event_number)); 330 } 331 332 /* 333 * Search for an audit_event entry with a given event_name and returns the 334 * corresponding event number. 335 */ 336 au_event_t * 337 getauevnonam_r(au_event_t *ev, const char *event_name) 338 { 339 static char event_ent_name[AU_EVENT_NAME_MAX]; 340 static char event_ent_desc[AU_EVENT_DESC_MAX]; 341 static struct au_event_ent e, *ep; 342 343 bzero(event_ent_name, sizeof(event_ent_name)); 344 bzero(event_ent_desc, sizeof(event_ent_desc)); 345 bzero(&e, sizeof(e)); 346 e.ae_name = event_ent_name; 347 e.ae_desc = event_ent_desc; 348 349 ep = getauevnam_r(&e, event_name); 350 if (ep == NULL) 351 return (NULL); 352 353 *ev = e.ae_number; 354 return (ev); 355 } 356 357 au_event_t * 358 getauevnonam(const char *event_name) 359 { 360 static au_event_t event; 361 362 return (getauevnonam_r(&event, event_name)); 363 } 364