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