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