152267f74SRobert Watson /*- 206edd2f1SRobert Watson * Copyright (c) 2004, 2009 Apple Inc. 3bb97b418SRobert 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 * 30*aa772005SRobert Watson * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_control.c#41 $ 31ca0716f5SRobert Watson */ 32ca0716f5SRobert Watson 3352267f74SRobert Watson #include <config/config.h> 3452267f74SRobert Watson 35ca0716f5SRobert Watson #include <bsm/libbsm.h> 36ca0716f5SRobert Watson 3706edd2f1SRobert Watson #include <ctype.h> 38ca0716f5SRobert Watson #include <errno.h> 39ca0716f5SRobert Watson #include <string.h> 40*aa772005SRobert Watson #include <strings.h> 417a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 42ca0716f5SRobert Watson #include <pthread.h> 437a0a89d2SRobert Watson #endif 44ca0716f5SRobert Watson #include <stdio.h> 45ca0716f5SRobert Watson #include <stdlib.h> 46ca0716f5SRobert Watson 47bb97b418SRobert Watson #ifndef HAVE_STRLCAT 48bb97b418SRobert Watson #include <compat/strlcat.h> 49bb97b418SRobert Watson #endif 5052267f74SRobert Watson #ifndef HAVE_STRLCPY 5152267f74SRobert Watson #include <compat/strlcpy.h> 5252267f74SRobert Watson #endif 53bb97b418SRobert Watson 54c0020399SRobert Watson #include <sys/stat.h> 55c0020399SRobert Watson 56ca0716f5SRobert Watson /* 57ca0716f5SRobert Watson * Parse the contents of the audit_control file to return the audit control 58bb97b418SRobert Watson * parameters. These static fields are protected by 'mutex'. 59ca0716f5SRobert Watson */ 60ca0716f5SRobert Watson static FILE *fp = NULL; 61ca0716f5SRobert Watson static char linestr[AU_LINE_MAX]; 62ca0716f5SRobert Watson static char *delim = ":"; 63ca0716f5SRobert Watson 64ca0716f5SRobert Watson static char inacdir = 0; 65ca0716f5SRobert Watson static char ptrmoved = 0; 66ca0716f5SRobert Watson 677a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 68ca0716f5SRobert Watson static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 697a0a89d2SRobert Watson #endif 70ca0716f5SRobert Watson 71ca0716f5SRobert Watson /* 7206edd2f1SRobert Watson * Audit policy string token table for au_poltostr() and au_strtopol(). 7306edd2f1SRobert Watson */ 7406edd2f1SRobert Watson struct audit_polstr { 7506edd2f1SRobert Watson long ap_policy; 7606edd2f1SRobert Watson const char *ap_str; 7706edd2f1SRobert Watson }; 7806edd2f1SRobert Watson 7906edd2f1SRobert Watson static struct audit_polstr au_polstr[] = { 8006edd2f1SRobert Watson { AUDIT_CNT, "cnt" }, 8106edd2f1SRobert Watson { AUDIT_AHLT, "ahlt" }, 8206edd2f1SRobert Watson { AUDIT_ARGV, "argv" }, 8306edd2f1SRobert Watson { AUDIT_ARGE, "arge" }, 8406edd2f1SRobert Watson { AUDIT_SEQ, "seq" }, 8506edd2f1SRobert Watson { AUDIT_WINDATA, "windata" }, 8606edd2f1SRobert Watson { AUDIT_USER, "user" }, 8706edd2f1SRobert Watson { AUDIT_GROUP, "group" }, 8806edd2f1SRobert Watson { AUDIT_TRAIL, "trail" }, 8906edd2f1SRobert Watson { AUDIT_PATH, "path" }, 9006edd2f1SRobert Watson { AUDIT_SCNT, "scnt" }, 9106edd2f1SRobert Watson { AUDIT_PUBLIC, "public" }, 9206edd2f1SRobert Watson { AUDIT_ZONENAME, "zonename" }, 9306edd2f1SRobert Watson { AUDIT_PERZONE, "perzone" }, 9406edd2f1SRobert Watson { -1, NULL } 9506edd2f1SRobert Watson }; 9606edd2f1SRobert Watson 9706edd2f1SRobert Watson /* 98ca0716f5SRobert Watson * Returns the string value corresponding to the given label from the 99ca0716f5SRobert Watson * configuration file. 100ca0716f5SRobert Watson * 101ca0716f5SRobert Watson * Must be called with mutex held. 102ca0716f5SRobert Watson */ 103ca0716f5SRobert Watson static int 104*aa772005SRobert Watson getstrfromtype_locked(const char *name, char **str) 105ca0716f5SRobert Watson { 106ca0716f5SRobert Watson char *type, *nl; 107ca0716f5SRobert Watson char *tokptr; 108ca0716f5SRobert Watson char *last; 109ca0716f5SRobert Watson 110ca0716f5SRobert Watson *str = NULL; 111ca0716f5SRobert Watson 112ca0716f5SRobert Watson if ((fp == NULL) && ((fp = fopen(AUDIT_CONTROL_FILE, "r")) == NULL)) 113ca0716f5SRobert Watson return (-1); /* Error */ 114ca0716f5SRobert Watson 115ca0716f5SRobert Watson while (1) { 116ca0716f5SRobert Watson if (fgets(linestr, AU_LINE_MAX, fp) == NULL) { 117ca0716f5SRobert Watson if (ferror(fp)) 118ca0716f5SRobert Watson return (-1); 119ca0716f5SRobert Watson return (0); /* EOF */ 120ca0716f5SRobert Watson } 121ca0716f5SRobert Watson 122ca0716f5SRobert Watson if (linestr[0] == '#') 123ca0716f5SRobert Watson continue; 124ca0716f5SRobert Watson 125597df30eSRobert Watson /* Remove trailing new line character and white space. */ 126597df30eSRobert Watson nl = strchr(linestr, '\0') - 1; 127597df30eSRobert Watson while (nl >= linestr && ('\n' == *nl || ' ' == *nl || 128597df30eSRobert Watson '\t' == *nl)) { 129ca0716f5SRobert Watson *nl = '\0'; 130597df30eSRobert Watson nl--; 131597df30eSRobert Watson } 132ca0716f5SRobert Watson 133ca0716f5SRobert Watson tokptr = linestr; 134ca0716f5SRobert Watson if ((type = strtok_r(tokptr, delim, &last)) != NULL) { 135ca0716f5SRobert Watson if (strcmp(name, type) == 0) { 136ca0716f5SRobert Watson /* Found matching name. */ 137ca0716f5SRobert Watson *str = strtok_r(NULL, delim, &last); 138ca0716f5SRobert Watson if (*str == NULL) { 139ca0716f5SRobert Watson errno = EINVAL; 140ca0716f5SRobert Watson return (-1); /* Parse error in file */ 141ca0716f5SRobert Watson } 142ca0716f5SRobert Watson return (0); /* Success */ 143ca0716f5SRobert Watson } 144ca0716f5SRobert Watson } 145ca0716f5SRobert Watson } 146ca0716f5SRobert Watson } 147ca0716f5SRobert Watson 148ca0716f5SRobert Watson /* 14906edd2f1SRobert Watson * Convert a given time value with a multiplier (seconds, hours, days, years) to 15006edd2f1SRobert Watson * seconds. Return 0 on success. 15106edd2f1SRobert Watson */ 15206edd2f1SRobert Watson static int 15306edd2f1SRobert Watson au_timetosec(time_t *seconds, u_long value, char mult) 15406edd2f1SRobert Watson { 15506edd2f1SRobert Watson if (NULL == seconds) 15606edd2f1SRobert Watson return (-1); 15706edd2f1SRobert Watson 15806edd2f1SRobert Watson switch(mult) { 15906edd2f1SRobert Watson case 's': 16006edd2f1SRobert Watson /* seconds */ 16106edd2f1SRobert Watson *seconds = (time_t)value; 16206edd2f1SRobert Watson break; 16306edd2f1SRobert Watson 16406edd2f1SRobert Watson case 'h': 16506edd2f1SRobert Watson /* hours */ 16606edd2f1SRobert Watson *seconds = (time_t)value * 60 * 60; 16706edd2f1SRobert Watson break; 16806edd2f1SRobert Watson 16906edd2f1SRobert Watson case 'd': 17006edd2f1SRobert Watson /* days */ 17106edd2f1SRobert Watson *seconds = (time_t)value * 60 * 60 * 24; 17206edd2f1SRobert Watson break; 17306edd2f1SRobert Watson 17406edd2f1SRobert Watson case 'y': 17506edd2f1SRobert Watson /* years. Add a day for each 4th (leap) year. */ 17606edd2f1SRobert Watson *seconds = (time_t)value * 60 * 60 * 24 * 364 + 17706edd2f1SRobert Watson ((time_t)value / 4) * 60 * 60 * 24; 17806edd2f1SRobert Watson break; 17906edd2f1SRobert Watson 18006edd2f1SRobert Watson default: 18106edd2f1SRobert Watson return (-1); 18206edd2f1SRobert Watson } 18306edd2f1SRobert Watson return (0); 18406edd2f1SRobert Watson } 18506edd2f1SRobert Watson 18606edd2f1SRobert Watson /* 18706edd2f1SRobert Watson * Convert a given disk space value with a multiplier (bytes, kilobytes, 18806edd2f1SRobert Watson * megabytes, gigabytes) to bytes. Return 0 on success. 18906edd2f1SRobert Watson */ 19006edd2f1SRobert Watson static int 19106edd2f1SRobert Watson au_spacetobytes(size_t *bytes, u_long value, char mult) 19206edd2f1SRobert Watson { 19306edd2f1SRobert Watson if (NULL == bytes) 19406edd2f1SRobert Watson return (-1); 19506edd2f1SRobert Watson 19606edd2f1SRobert Watson switch(mult) { 19706edd2f1SRobert Watson case 'B': 19806edd2f1SRobert Watson case ' ': 19906edd2f1SRobert Watson /* Bytes */ 20006edd2f1SRobert Watson *bytes = (size_t)value; 20106edd2f1SRobert Watson break; 20206edd2f1SRobert Watson 20306edd2f1SRobert Watson case 'K': 20406edd2f1SRobert Watson /* Kilobytes */ 20506edd2f1SRobert Watson *bytes = (size_t)value * 1024; 20606edd2f1SRobert Watson break; 20706edd2f1SRobert Watson 20806edd2f1SRobert Watson case 'M': 20906edd2f1SRobert Watson /* Megabytes */ 21006edd2f1SRobert Watson *bytes = (size_t)value * 1024 * 1024; 21106edd2f1SRobert Watson break; 21206edd2f1SRobert Watson 21306edd2f1SRobert Watson case 'G': 21406edd2f1SRobert Watson /* Gigabytes */ 21506edd2f1SRobert Watson *bytes = (size_t)value * 1024 * 1024 * 1024; 21606edd2f1SRobert Watson break; 21706edd2f1SRobert Watson 21806edd2f1SRobert Watson default: 21906edd2f1SRobert Watson return (-1); 22006edd2f1SRobert Watson } 22106edd2f1SRobert Watson return (0); 22206edd2f1SRobert Watson } 22306edd2f1SRobert Watson 22406edd2f1SRobert Watson /* 225bb97b418SRobert Watson * Convert a policy to a string. Return -1 on failure, or >= 0 representing 226bb97b418SRobert Watson * the actual size of the string placed in the buffer (excluding terminating 227bb97b418SRobert Watson * nul). 228bb97b418SRobert Watson */ 229bb97b418SRobert Watson ssize_t 230c0020399SRobert Watson au_poltostr(int policy, size_t maxsize, char *buf) 231bb97b418SRobert Watson { 23206edd2f1SRobert Watson int first = 1; 23306edd2f1SRobert Watson int i = 0; 234bb97b418SRobert Watson 235bb97b418SRobert Watson if (maxsize < 1) 236bb97b418SRobert Watson return (-1); 237bb97b418SRobert Watson buf[0] = '\0'; 238bb97b418SRobert Watson 23906edd2f1SRobert Watson do { 24006edd2f1SRobert Watson if (policy & au_polstr[i].ap_policy) { 24106edd2f1SRobert Watson if (!first && strlcat(buf, ",", maxsize) >= maxsize) 24206edd2f1SRobert Watson return (-1); 24306edd2f1SRobert Watson if (strlcat(buf, au_polstr[i].ap_str, maxsize) >= 24406edd2f1SRobert Watson maxsize) 245bb97b418SRobert Watson return (-1); 246bb97b418SRobert Watson first = 0; 247bb97b418SRobert Watson } 24806edd2f1SRobert Watson } while (NULL != au_polstr[++i].ap_str); 24906edd2f1SRobert Watson 250bb97b418SRobert Watson return (strlen(buf)); 251bb97b418SRobert Watson } 252bb97b418SRobert Watson 253bb97b418SRobert Watson /* 254bb97b418SRobert Watson * Convert a string to a policy. Return -1 on failure (with errno EINVAL, 255bb97b418SRobert Watson * ENOMEM) or 0 on success. 256bb97b418SRobert Watson */ 257bb97b418SRobert Watson int 258c0020399SRobert Watson au_strtopol(const char *polstr, int *policy) 259bb97b418SRobert Watson { 260bb97b418SRobert Watson char *bufp, *string; 261bb97b418SRobert Watson char *buffer; 26206edd2f1SRobert Watson int i, matched; 263bb97b418SRobert Watson 264bb97b418SRobert Watson *policy = 0; 265bb97b418SRobert Watson buffer = strdup(polstr); 266bb97b418SRobert Watson if (buffer == NULL) 267bb97b418SRobert Watson return (-1); 268bb97b418SRobert Watson 269bb97b418SRobert Watson bufp = buffer; 270bb97b418SRobert Watson while ((string = strsep(&bufp, ",")) != NULL) { 27106edd2f1SRobert Watson matched = i = 0; 27206edd2f1SRobert Watson 27306edd2f1SRobert Watson do { 27406edd2f1SRobert Watson if (strcmp(string, au_polstr[i].ap_str) == 0) { 27506edd2f1SRobert Watson *policy |= au_polstr[i].ap_policy; 27606edd2f1SRobert Watson matched = 1; 27706edd2f1SRobert Watson break; 27806edd2f1SRobert Watson } 27906edd2f1SRobert Watson } while (NULL != au_polstr[++i].ap_str); 28006edd2f1SRobert Watson 28106edd2f1SRobert Watson if (!matched) { 282bb97b418SRobert Watson free(buffer); 283bb97b418SRobert Watson errno = EINVAL; 284bb97b418SRobert Watson return (-1); 285bb97b418SRobert Watson } 286bb97b418SRobert Watson } 287bb97b418SRobert Watson free(buffer); 288bb97b418SRobert Watson return (0); 289bb97b418SRobert Watson } 290bb97b418SRobert Watson 291bb97b418SRobert Watson /* 292ca0716f5SRobert Watson * Rewind the file pointer to beginning. 293ca0716f5SRobert Watson */ 294bb97b418SRobert Watson static void 295bb97b418SRobert Watson setac_locked(void) 296bb97b418SRobert Watson { 297c0020399SRobert Watson static time_t lastctime = 0; 298c0020399SRobert Watson struct stat sbuf; 299bb97b418SRobert Watson 300bb97b418SRobert Watson ptrmoved = 1; 301c0020399SRobert Watson if (fp != NULL) { 302c0020399SRobert Watson /* 303c0020399SRobert Watson * Check to see if the file on disk has changed. If so, 304c0020399SRobert Watson * force a re-read of the file by closing it. 305c0020399SRobert Watson */ 306c0020399SRobert Watson if (fstat(fileno(fp), &sbuf) < 0) 307c0020399SRobert Watson goto closefp; 308c0020399SRobert Watson if (lastctime != sbuf.st_ctime) { 309c0020399SRobert Watson lastctime = sbuf.st_ctime; 310c0020399SRobert Watson closefp: 311c0020399SRobert Watson fclose(fp); 312c0020399SRobert Watson fp = NULL; 313c0020399SRobert Watson return; 314c0020399SRobert Watson } 315c0020399SRobert Watson 316bb97b418SRobert Watson fseek(fp, 0, SEEK_SET); 317bb97b418SRobert Watson } 318c0020399SRobert Watson } 319bb97b418SRobert Watson 320ca0716f5SRobert Watson void 321ca0716f5SRobert Watson setac(void) 322ca0716f5SRobert Watson { 323ca0716f5SRobert Watson 3247a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 325ca0716f5SRobert Watson pthread_mutex_lock(&mutex); 3267a0a89d2SRobert Watson #endif 327bb97b418SRobert Watson setac_locked(); 3287a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 329ca0716f5SRobert Watson pthread_mutex_unlock(&mutex); 3307a0a89d2SRobert Watson #endif 331ca0716f5SRobert Watson } 332ca0716f5SRobert Watson 333ca0716f5SRobert Watson /* 334bb97b418SRobert Watson * Close the audit_control file. 335ca0716f5SRobert Watson */ 336ca0716f5SRobert Watson void 337ca0716f5SRobert Watson endac(void) 338ca0716f5SRobert Watson { 339ca0716f5SRobert Watson 3407a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 341ca0716f5SRobert Watson pthread_mutex_lock(&mutex); 3427a0a89d2SRobert Watson #endif 343ca0716f5SRobert Watson ptrmoved = 1; 344ca0716f5SRobert Watson if (fp != NULL) { 345ca0716f5SRobert Watson fclose(fp); 346ca0716f5SRobert Watson fp = NULL; 347ca0716f5SRobert Watson } 3487a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 349ca0716f5SRobert Watson pthread_mutex_unlock(&mutex); 3507a0a89d2SRobert Watson #endif 351ca0716f5SRobert Watson } 352ca0716f5SRobert Watson 353ca0716f5SRobert Watson /* 354ca0716f5SRobert Watson * Return audit directory information from the audit control file. 355ca0716f5SRobert Watson */ 356ca0716f5SRobert Watson int 357ca0716f5SRobert Watson getacdir(char *name, int len) 358ca0716f5SRobert Watson { 359ca0716f5SRobert Watson char *dir; 360ca0716f5SRobert Watson int ret = 0; 361ca0716f5SRobert Watson 362ca0716f5SRobert Watson /* 363bb97b418SRobert Watson * Check if another function was called between successive calls to 364bb97b418SRobert Watson * getacdir. 365ca0716f5SRobert Watson */ 3667a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 367bb97b418SRobert Watson pthread_mutex_lock(&mutex); 3687a0a89d2SRobert Watson #endif 369ca0716f5SRobert Watson if (inacdir && ptrmoved) { 370ca0716f5SRobert Watson ptrmoved = 0; 371ca0716f5SRobert Watson if (fp != NULL) 372ca0716f5SRobert Watson fseek(fp, 0, SEEK_SET); 373ca0716f5SRobert Watson ret = 2; 374ca0716f5SRobert Watson } 375ca0716f5SRobert Watson if (getstrfromtype_locked(DIR_CONTROL_ENTRY, &dir) < 0) { 3767a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 377ca0716f5SRobert Watson pthread_mutex_unlock(&mutex); 3787a0a89d2SRobert Watson #endif 379ca0716f5SRobert Watson return (-2); 380ca0716f5SRobert Watson } 381bb97b418SRobert Watson if (dir == NULL) { 3827a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 383ca0716f5SRobert Watson pthread_mutex_unlock(&mutex); 3847a0a89d2SRobert Watson #endif 385ca0716f5SRobert Watson return (-1); 386bb97b418SRobert Watson } 38752267f74SRobert Watson if (strlen(dir) >= (size_t)len) { 3887a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 389bb97b418SRobert Watson pthread_mutex_unlock(&mutex); 3907a0a89d2SRobert Watson #endif 391ca0716f5SRobert Watson return (-3); 392bb97b418SRobert Watson } 39352267f74SRobert Watson strlcpy(name, dir, len); 3947a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 395bb97b418SRobert Watson pthread_mutex_unlock(&mutex); 3967a0a89d2SRobert Watson #endif 397ca0716f5SRobert Watson return (ret); 398ca0716f5SRobert Watson } 399ca0716f5SRobert Watson 400ca0716f5SRobert Watson /* 401*aa772005SRobert Watson * Return 1 if dist value is set to 'yes' or 'on'. 402*aa772005SRobert Watson * Return 0 if dist value is set to something else. 403*aa772005SRobert Watson * Return negative value on error. 404*aa772005SRobert Watson */ 405*aa772005SRobert Watson int 406*aa772005SRobert Watson getacdist(void) 407*aa772005SRobert Watson { 408*aa772005SRobert Watson char *str; 409*aa772005SRobert Watson int ret; 410*aa772005SRobert Watson 411*aa772005SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 412*aa772005SRobert Watson pthread_mutex_lock(&mutex); 413*aa772005SRobert Watson #endif 414*aa772005SRobert Watson setac_locked(); 415*aa772005SRobert Watson if (getstrfromtype_locked(DIST_CONTROL_ENTRY, &str) < 0) { 416*aa772005SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 417*aa772005SRobert Watson pthread_mutex_unlock(&mutex); 418*aa772005SRobert Watson #endif 419*aa772005SRobert Watson return (-2); 420*aa772005SRobert Watson } 421*aa772005SRobert Watson if (str == NULL) { 422*aa772005SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 423*aa772005SRobert Watson pthread_mutex_unlock(&mutex); 424*aa772005SRobert Watson #endif 425*aa772005SRobert Watson return (0); 426*aa772005SRobert Watson } 427*aa772005SRobert Watson if (strcasecmp(str, "on") == 0 || strcasecmp(str, "yes") == 0) 428*aa772005SRobert Watson ret = 1; 429*aa772005SRobert Watson else 430*aa772005SRobert Watson ret = 0; 431*aa772005SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 432*aa772005SRobert Watson pthread_mutex_unlock(&mutex); 433*aa772005SRobert Watson #endif 434*aa772005SRobert Watson return (ret); 435*aa772005SRobert Watson } 436*aa772005SRobert Watson 437*aa772005SRobert Watson /* 438bb97b418SRobert Watson * Return the minimum free diskspace value from the audit control file. 439ca0716f5SRobert Watson */ 440ca0716f5SRobert Watson int 441ca0716f5SRobert Watson getacmin(int *min_val) 442ca0716f5SRobert Watson { 443ca0716f5SRobert Watson char *min; 444ca0716f5SRobert Watson 4457a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 446ca0716f5SRobert Watson pthread_mutex_lock(&mutex); 4477a0a89d2SRobert Watson #endif 448bb97b418SRobert Watson setac_locked(); 449ca0716f5SRobert Watson if (getstrfromtype_locked(MINFREE_CONTROL_ENTRY, &min) < 0) { 4507a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 451ca0716f5SRobert Watson pthread_mutex_unlock(&mutex); 4527a0a89d2SRobert Watson #endif 453ca0716f5SRobert Watson return (-2); 454ca0716f5SRobert Watson } 455bb97b418SRobert Watson if (min == NULL) { 4567a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 457ca0716f5SRobert Watson pthread_mutex_unlock(&mutex); 4587a0a89d2SRobert Watson #endif 459*aa772005SRobert Watson return (-1); 460bb97b418SRobert Watson } 461ca0716f5SRobert Watson *min_val = atoi(min); 4627a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 463bb97b418SRobert Watson pthread_mutex_unlock(&mutex); 4647a0a89d2SRobert Watson #endif 465ca0716f5SRobert Watson return (0); 466ca0716f5SRobert Watson } 467ca0716f5SRobert Watson 468ca0716f5SRobert Watson /* 4694bd0c025SRobert Watson * Return the desired trail rotation size from the audit control file. 4704bd0c025SRobert Watson */ 4714bd0c025SRobert Watson int 4724bd0c025SRobert Watson getacfilesz(size_t *filesz_val) 4734bd0c025SRobert Watson { 47406edd2f1SRobert Watson char *str; 47506edd2f1SRobert Watson size_t val; 47606edd2f1SRobert Watson char mult; 47706edd2f1SRobert Watson int nparsed; 4784bd0c025SRobert Watson 4797a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 4804bd0c025SRobert Watson pthread_mutex_lock(&mutex); 4817a0a89d2SRobert Watson #endif 4824bd0c025SRobert Watson setac_locked(); 48306edd2f1SRobert Watson if (getstrfromtype_locked(FILESZ_CONTROL_ENTRY, &str) < 0) { 4847a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 4854bd0c025SRobert Watson pthread_mutex_unlock(&mutex); 4867a0a89d2SRobert Watson #endif 4874bd0c025SRobert Watson return (-2); 4884bd0c025SRobert Watson } 48906edd2f1SRobert Watson if (str == NULL) { 4907a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 4914bd0c025SRobert Watson pthread_mutex_unlock(&mutex); 4927a0a89d2SRobert Watson #endif 4934bd0c025SRobert Watson errno = EINVAL; 494*aa772005SRobert Watson return (-1); 4954bd0c025SRobert Watson } 49606edd2f1SRobert Watson 49706edd2f1SRobert Watson /* Trim off any leading white space. */ 49806edd2f1SRobert Watson while (*str == ' ' || *str == '\t') 49906edd2f1SRobert Watson str++; 50006edd2f1SRobert Watson 50106edd2f1SRobert Watson nparsed = sscanf(str, "%ju%c", (uintmax_t *)&val, &mult); 50206edd2f1SRobert Watson 50306edd2f1SRobert Watson switch (nparsed) { 50406edd2f1SRobert Watson case 1: 50506edd2f1SRobert Watson /* If no multiplier then assume 'B' (bytes). */ 50606edd2f1SRobert Watson mult = 'B'; 50706edd2f1SRobert Watson /* fall through */ 50806edd2f1SRobert Watson case 2: 50906edd2f1SRobert Watson if (au_spacetobytes(filesz_val, val, mult) == 0) 51006edd2f1SRobert Watson break; 51106edd2f1SRobert Watson /* fall through */ 51206edd2f1SRobert Watson default: 51306edd2f1SRobert Watson errno = EINVAL; 5147a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 5154bd0c025SRobert Watson pthread_mutex_unlock(&mutex); 5167a0a89d2SRobert Watson #endif 5174bd0c025SRobert Watson return (-1); 5184bd0c025SRobert Watson } 51906edd2f1SRobert Watson 5204bd0c025SRobert Watson /* 5214bd0c025SRobert Watson * The file size must either be 0 or >= MIN_AUDIT_FILE_SIZE. 0 5224bd0c025SRobert Watson * indicates no rotation size. 5234bd0c025SRobert Watson */ 52406edd2f1SRobert Watson if (*filesz_val < 0 || (*filesz_val > 0 && 52506edd2f1SRobert Watson *filesz_val < MIN_AUDIT_FILE_SIZE)) { 5267a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 5274bd0c025SRobert Watson pthread_mutex_unlock(&mutex); 5287a0a89d2SRobert Watson #endif 52906edd2f1SRobert Watson filesz_val = 0L; 5304bd0c025SRobert Watson errno = EINVAL; 5314bd0c025SRobert Watson return (-1); 5324bd0c025SRobert Watson } 5337a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 5344bd0c025SRobert Watson pthread_mutex_unlock(&mutex); 5357a0a89d2SRobert Watson #endif 5364bd0c025SRobert Watson return (0); 5374bd0c025SRobert Watson } 5384bd0c025SRobert Watson 539*aa772005SRobert Watson static int 540*aa772005SRobert Watson getaccommon(const char *name, char *auditstr, int len) 541ca0716f5SRobert Watson { 542ca0716f5SRobert Watson char *str; 543ca0716f5SRobert Watson 5447a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 545ca0716f5SRobert Watson pthread_mutex_lock(&mutex); 5467a0a89d2SRobert Watson #endif 547bb97b418SRobert Watson setac_locked(); 548*aa772005SRobert Watson if (getstrfromtype_locked(name, &str) < 0) { 5497a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 550bb97b418SRobert Watson pthread_mutex_unlock(&mutex); 5517a0a89d2SRobert Watson #endif 552bb97b418SRobert Watson return (-2); 553bb97b418SRobert Watson } 554bb97b418SRobert Watson if (str == NULL) { 5557a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 556bb97b418SRobert Watson pthread_mutex_unlock(&mutex); 5577a0a89d2SRobert Watson #endif 558bb97b418SRobert Watson return (-1); 559bb97b418SRobert Watson } 560*aa772005SRobert Watson if (strlen(str) >= (size_t)len) { 5617a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 562bb97b418SRobert Watson pthread_mutex_unlock(&mutex); 5637a0a89d2SRobert Watson #endif 564bb97b418SRobert Watson return (-3); 565bb97b418SRobert Watson } 56652267f74SRobert Watson strlcpy(auditstr, str, len); 5677a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 56852267f74SRobert Watson pthread_mutex_unlock(&mutex); 5697a0a89d2SRobert Watson #endif 57052267f74SRobert Watson return (0); 57152267f74SRobert Watson } 57252267f74SRobert Watson 573*aa772005SRobert Watson /* 574*aa772005SRobert Watson * Return the system audit value from the audit contol file. 575*aa772005SRobert Watson */ 576*aa772005SRobert Watson int 577*aa772005SRobert Watson getacflg(char *auditstr, int len) 578*aa772005SRobert Watson { 579*aa772005SRobert Watson 580*aa772005SRobert Watson return (getaccommon(FLAGS_CONTROL_ENTRY, auditstr, len)); 581*aa772005SRobert Watson } 582*aa772005SRobert Watson 583*aa772005SRobert Watson /* 584*aa772005SRobert Watson * Return the non attributable flags from the audit contol file. 585*aa772005SRobert Watson */ 586*aa772005SRobert Watson int 587*aa772005SRobert Watson getacna(char *auditstr, int len) 588*aa772005SRobert Watson { 589*aa772005SRobert Watson 590*aa772005SRobert Watson return (getaccommon(NA_CONTROL_ENTRY, auditstr, len)); 591*aa772005SRobert Watson } 592*aa772005SRobert Watson 593*aa772005SRobert Watson /* 594*aa772005SRobert Watson * Return the policy field from the audit control file. 595*aa772005SRobert Watson */ 596*aa772005SRobert Watson int 597*aa772005SRobert Watson getacpol(char *auditstr, size_t len) 598*aa772005SRobert Watson { 599*aa772005SRobert Watson 600*aa772005SRobert Watson return (getaccommon(POLICY_CONTROL_ENTRY, auditstr, len)); 601*aa772005SRobert Watson } 602*aa772005SRobert Watson 60352267f74SRobert Watson int 60452267f74SRobert Watson getachost(char *auditstr, size_t len) 60552267f74SRobert Watson { 60652267f74SRobert Watson 607*aa772005SRobert Watson return (getaccommon(HOST_CONTROL_ENTRY, auditstr, len)); 60806edd2f1SRobert Watson } 60906edd2f1SRobert Watson 61006edd2f1SRobert Watson /* 61106edd2f1SRobert Watson * Set expiration conditions. 61206edd2f1SRobert Watson */ 61306edd2f1SRobert Watson static int 61406edd2f1SRobert Watson setexpirecond(time_t *age, size_t *size, u_long value, char mult) 61506edd2f1SRobert Watson { 61606edd2f1SRobert Watson 61706edd2f1SRobert Watson if (isupper(mult) || ' ' == mult) 61806edd2f1SRobert Watson return (au_spacetobytes(size, value, mult)); 61906edd2f1SRobert Watson else 62006edd2f1SRobert Watson return (au_timetosec(age, value, mult)); 62106edd2f1SRobert Watson } 62206edd2f1SRobert Watson 62306edd2f1SRobert Watson /* 62406edd2f1SRobert Watson * Return the expire-after field from the audit control file. 62506edd2f1SRobert Watson */ 62606edd2f1SRobert Watson int 62706edd2f1SRobert Watson getacexpire(int *andflg, time_t *age, size_t *size) 62806edd2f1SRobert Watson { 62906edd2f1SRobert Watson char *str; 63006edd2f1SRobert Watson int nparsed; 63106edd2f1SRobert Watson u_long val1, val2; 63206edd2f1SRobert Watson char mult1, mult2; 63306edd2f1SRobert Watson char andor[AU_LINE_MAX]; 63406edd2f1SRobert Watson 63506edd2f1SRobert Watson *age = 0L; 63606edd2f1SRobert Watson *size = 0LL; 63706edd2f1SRobert Watson *andflg = 0; 63806edd2f1SRobert Watson 63906edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 64006edd2f1SRobert Watson pthread_mutex_lock(&mutex); 64106edd2f1SRobert Watson #endif 64206edd2f1SRobert Watson setac_locked(); 64306edd2f1SRobert Watson if (getstrfromtype_locked(EXPIRE_AFTER_CONTROL_ENTRY, &str) < 0) { 64406edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 64506edd2f1SRobert Watson pthread_mutex_unlock(&mutex); 64606edd2f1SRobert Watson #endif 64706edd2f1SRobert Watson return (-2); 64806edd2f1SRobert Watson } 64906edd2f1SRobert Watson if (str == NULL) { 65006edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 65106edd2f1SRobert Watson pthread_mutex_unlock(&mutex); 65206edd2f1SRobert Watson #endif 653*aa772005SRobert Watson return (-1); 65406edd2f1SRobert Watson } 65506edd2f1SRobert Watson 65606edd2f1SRobert Watson /* First, trim off any leading white space. */ 65706edd2f1SRobert Watson while (*str == ' ' || *str == '\t') 65806edd2f1SRobert Watson str++; 65906edd2f1SRobert Watson 66006edd2f1SRobert Watson nparsed = sscanf(str, "%lu%c%[ \tadnorADNOR]%lu%c", &val1, &mult1, 66106edd2f1SRobert Watson andor, &val2, &mult2); 66206edd2f1SRobert Watson 66306edd2f1SRobert Watson switch (nparsed) { 66406edd2f1SRobert Watson case 1: 66506edd2f1SRobert Watson /* If no multiplier then assume 'B' (Bytes). */ 66606edd2f1SRobert Watson mult1 = 'B'; 66706edd2f1SRobert Watson /* fall through */ 66806edd2f1SRobert Watson case 2: 66906edd2f1SRobert Watson /* One expiration condition. */ 67006edd2f1SRobert Watson if (setexpirecond(age, size, val1, mult1) != 0) { 67106edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 67206edd2f1SRobert Watson pthread_mutex_unlock(&mutex); 67306edd2f1SRobert Watson #endif 67406edd2f1SRobert Watson return (-1); 67506edd2f1SRobert Watson } 67606edd2f1SRobert Watson break; 67706edd2f1SRobert Watson 67806edd2f1SRobert Watson case 5: 67906edd2f1SRobert Watson /* Two expiration conditions. */ 68006edd2f1SRobert Watson if (setexpirecond(age, size, val1, mult1) != 0 || 68106edd2f1SRobert Watson setexpirecond(age, size, val2, mult2) != 0) { 68206edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 68306edd2f1SRobert Watson pthread_mutex_unlock(&mutex); 68406edd2f1SRobert Watson #endif 68506edd2f1SRobert Watson return (-1); 68606edd2f1SRobert Watson } 68706edd2f1SRobert Watson if (strcasestr(andor, "and") != NULL) 68806edd2f1SRobert Watson *andflg = 1; 68906edd2f1SRobert Watson else if (strcasestr(andor, "or") != NULL) 69006edd2f1SRobert Watson *andflg = 0; 69106edd2f1SRobert Watson else { 69206edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 69306edd2f1SRobert Watson pthread_mutex_unlock(&mutex); 69406edd2f1SRobert Watson #endif 69506edd2f1SRobert Watson return (-1); 69606edd2f1SRobert Watson } 69706edd2f1SRobert Watson break; 69806edd2f1SRobert Watson 69906edd2f1SRobert Watson default: 70006edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 70106edd2f1SRobert Watson pthread_mutex_unlock(&mutex); 70206edd2f1SRobert Watson #endif 70306edd2f1SRobert Watson return (-1); 70406edd2f1SRobert Watson } 70506edd2f1SRobert Watson 7067a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK 707bb97b418SRobert Watson pthread_mutex_unlock(&mutex); 7087a0a89d2SRobert Watson #endif 709ca0716f5SRobert Watson return (0); 710ca0716f5SRobert Watson } 711