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 31 #include <config/config.h> 32 33 #include <bsm/libbsm.h> 34 35 #include <string.h> 36 #ifdef HAVE_PTHREAD_MUTEX_LOCK 37 #include <pthread.h> 38 #endif 39 #include <stdio.h> 40 #include <stdlib.h> 41 42 #ifndef HAVE_STRLCPY 43 #include <compat/strlcpy.h> 44 #endif 45 46 47 /* 48 * Parse the contents of the audit_event file to return 49 * au_event_ent entries 50 */ 51 static FILE *fp = NULL; 52 static char linestr[AU_LINE_MAX]; 53 static const char *eventdelim = ":"; 54 55 #ifdef HAVE_PTHREAD_MUTEX_LOCK 56 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 57 #endif 58 59 /* 60 * Parse one line from the audit_event file into the au_event_ent structure. 61 */ 62 static struct au_event_ent * 63 eventfromstr(char *str, struct au_event_ent *e) 64 { 65 char *evno, *evname, *evdesc, *evclass; 66 struct au_mask evmask; 67 char *last; 68 69 evno = strtok_r(str, eventdelim, &last); 70 evname = strtok_r(NULL, eventdelim, &last); 71 evdesc = strtok_r(NULL, eventdelim, &last); 72 evclass = strtok_r(NULL, eventdelim, &last); 73 74 if ((evno == NULL) || (evname == NULL)) 75 return (NULL); 76 77 if (strlen(evname) >= AU_EVENT_NAME_MAX) 78 return (NULL); 79 80 strlcpy(e->ae_name, evname, AU_EVENT_NAME_MAX); 81 if (evdesc != NULL) { 82 if (strlen(evdesc) >= AU_EVENT_DESC_MAX) 83 return (NULL); 84 strlcpy(e->ae_desc, evdesc, AU_EVENT_DESC_MAX); 85 } else 86 strlcpy(e->ae_desc, "", AU_EVENT_DESC_MAX); 87 88 e->ae_number = atoi(evno); 89 90 /* 91 * Find out the mask that corresponds to the given list of classes. 92 */ 93 if (evclass != NULL) { 94 if (getauditflagsbin(evclass, &evmask) != 0) 95 e->ae_class = 0; 96 else 97 e->ae_class = evmask.am_success; 98 } else 99 e->ae_class = 0; 100 101 return (e); 102 } 103 104 /* 105 * Rewind the audit_event file. 106 */ 107 static void 108 setauevent_locked(void) 109 { 110 111 if (fp != NULL) 112 fseek(fp, 0, SEEK_SET); 113 } 114 115 void 116 setauevent(void) 117 { 118 119 #ifdef HAVE_PTHREAD_MUTEX_LOCK 120 pthread_mutex_lock(&mutex); 121 #endif 122 setauevent_locked(); 123 #ifdef HAVE_PTHREAD_MUTEX_LOCK 124 pthread_mutex_unlock(&mutex); 125 #endif 126 } 127 128 /* 129 * Close the open file pointers. 130 */ 131 void 132 endauevent(void) 133 { 134 135 #ifdef HAVE_PTHREAD_MUTEX_LOCK 136 pthread_mutex_lock(&mutex); 137 #endif 138 if (fp != NULL) { 139 fclose(fp); 140 fp = NULL; 141 } 142 #ifdef HAVE_PTHREAD_MUTEX_LOCK 143 pthread_mutex_unlock(&mutex); 144 #endif 145 } 146 147 /* 148 * Enumerate the au_event_ent entries. 149 */ 150 static struct au_event_ent * 151 getauevent_r_locked(struct au_event_ent *e) 152 { 153 char *nl; 154 155 if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL)) 156 return (NULL); 157 158 while (1) { 159 if (fgets(linestr, AU_LINE_MAX, fp) == NULL) 160 return (NULL); 161 162 /* Remove new lines. */ 163 if ((nl = strrchr(linestr, '\n')) != NULL) 164 *nl = '\0'; 165 166 /* Skip comments. */ 167 if (linestr[0] == '#') 168 continue; 169 170 /* Get the next event structure. */ 171 if (eventfromstr(linestr, e) == NULL) 172 return (NULL); 173 break; 174 } 175 176 return (e); 177 } 178 179 struct au_event_ent * 180 getauevent_r(struct au_event_ent *e) 181 { 182 struct au_event_ent *ep; 183 184 #ifdef HAVE_PTHREAD_MUTEX_LOCK 185 pthread_mutex_lock(&mutex); 186 #endif 187 ep = getauevent_r_locked(e); 188 #ifdef HAVE_PTHREAD_MUTEX_LOCK 189 pthread_mutex_unlock(&mutex); 190 #endif 191 return (ep); 192 } 193 194 struct au_event_ent * 195 getauevent(void) 196 { 197 static char event_ent_name[AU_EVENT_NAME_MAX]; 198 static char event_ent_desc[AU_EVENT_DESC_MAX]; 199 static struct au_event_ent e; 200 201 bzero(&e, sizeof(e)); 202 bzero(event_ent_name, sizeof(event_ent_name)); 203 bzero(event_ent_desc, sizeof(event_ent_desc)); 204 e.ae_name = event_ent_name; 205 e.ae_desc = event_ent_desc; 206 return (getauevent_r(&e)); 207 } 208 209 /* 210 * Search for an audit event structure having the given event name. 211 * 212 * XXXRW: Why accept NULL name? 213 */ 214 static struct au_event_ent * 215 getauevnam_r_locked(struct au_event_ent *e, const char *name) 216 { 217 char *nl; 218 219 if (name == NULL) 220 return (NULL); 221 222 /* Rewind to beginning of the file. */ 223 setauevent_locked(); 224 225 if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL)) 226 return (NULL); 227 228 while (fgets(linestr, AU_LINE_MAX, fp) != NULL) { 229 /* Remove new lines. */ 230 if ((nl = strrchr(linestr, '\n')) != NULL) 231 *nl = '\0'; 232 233 if (eventfromstr(linestr, e) != NULL) { 234 if (strcmp(name, e->ae_name) == 0) 235 return (e); 236 } 237 } 238 239 return (NULL); 240 } 241 242 struct au_event_ent * 243 getauevnam_r(struct au_event_ent *e, const char *name) 244 { 245 struct au_event_ent *ep; 246 247 #ifdef HAVE_PTHREAD_MUTEX_LOCK 248 pthread_mutex_lock(&mutex); 249 #endif 250 ep = getauevnam_r_locked(e, name); 251 #ifdef HAVE_PTHREAD_MUTEX_LOCK 252 pthread_mutex_unlock(&mutex); 253 #endif 254 return (ep); 255 } 256 257 struct au_event_ent * 258 getauevnam(const char *name) 259 { 260 static char event_ent_name[AU_EVENT_NAME_MAX]; 261 static char event_ent_desc[AU_EVENT_DESC_MAX]; 262 static struct au_event_ent e; 263 264 bzero(&e, sizeof(e)); 265 bzero(event_ent_name, sizeof(event_ent_name)); 266 bzero(event_ent_desc, sizeof(event_ent_desc)); 267 e.ae_name = event_ent_name; 268 e.ae_desc = event_ent_desc; 269 return (getauevnam_r(&e, name)); 270 } 271 272 /* 273 * Search for an audit event structure having the given event number. 274 */ 275 static struct au_event_ent * 276 getauevnum_r_locked(struct au_event_ent *e, au_event_t event_number) 277 { 278 char *nl; 279 280 /* Rewind to beginning of the file. */ 281 setauevent_locked(); 282 283 if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL)) 284 return (NULL); 285 286 while (fgets(linestr, AU_LINE_MAX, fp) != NULL) { 287 /* Remove new lines. */ 288 if ((nl = strrchr(linestr, '\n')) != NULL) 289 *nl = '\0'; 290 291 if (eventfromstr(linestr, e) != NULL) { 292 if (event_number == e->ae_number) 293 return (e); 294 } 295 } 296 297 return (NULL); 298 } 299 300 struct au_event_ent * 301 getauevnum_r(struct au_event_ent *e, au_event_t event_number) 302 { 303 struct au_event_ent *ep; 304 305 #ifdef HAVE_PTHREAD_MUTEX_LOCK 306 pthread_mutex_lock(&mutex); 307 #endif 308 ep = getauevnum_r_locked(e, event_number); 309 #ifdef HAVE_PTHREAD_MUTEX_LOCK 310 pthread_mutex_unlock(&mutex); 311 #endif 312 return (ep); 313 } 314 315 struct au_event_ent * 316 getauevnum(au_event_t event_number) 317 { 318 static char event_ent_name[AU_EVENT_NAME_MAX]; 319 static char event_ent_desc[AU_EVENT_DESC_MAX]; 320 static struct au_event_ent e; 321 322 bzero(&e, sizeof(e)); 323 bzero(event_ent_name, sizeof(event_ent_name)); 324 bzero(event_ent_desc, sizeof(event_ent_desc)); 325 e.ae_name = event_ent_name; 326 e.ae_desc = event_ent_desc; 327 return (getauevnum_r(&e, event_number)); 328 } 329 330 /* 331 * Search for an audit_event entry with a given event_name and returns the 332 * corresponding event number. 333 */ 334 au_event_t * 335 getauevnonam_r(au_event_t *ev, const char *event_name) 336 { 337 static char event_ent_name[AU_EVENT_NAME_MAX]; 338 static char event_ent_desc[AU_EVENT_DESC_MAX]; 339 static struct au_event_ent e, *ep; 340 341 bzero(event_ent_name, sizeof(event_ent_name)); 342 bzero(event_ent_desc, sizeof(event_ent_desc)); 343 bzero(&e, sizeof(e)); 344 e.ae_name = event_ent_name; 345 e.ae_desc = event_ent_desc; 346 347 ep = getauevnam_r(&e, event_name); 348 if (ep == NULL) 349 return (NULL); 350 351 *ev = e.ae_number; 352 return (ev); 353 } 354 355 au_event_t * 356 getauevnonam(const char *event_name) 357 { 358 static au_event_t event; 359 360 return (getauevnonam_r(&event, event_name)); 361 } 362