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