2 * Copyright (c) 2004, 2009 Apple Inc.
3 * Copyright (c) 2006 Robert N. M. Watson
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
31 #include <config/config.h>
33 #include <bsm/libbsm.h>
39 #ifdef HAVE_PTHREAD_MUTEX_LOCK
46 #include <compat/strlcat.h>
49 #include <compat/strlcpy.h>
55 * Parse the contents of the audit_control file to return the audit control
56 * parameters. These static fields are protected by 'mutex'.
58 static FILE *fp = NULL;
59 static char linestr[AU_LINE_MAX];
60 static char *delim = ":";
62 static char inacdir = 0;
63 static char ptrmoved = 0;
65 #ifdef HAVE_PTHREAD_MUTEX_LOCK
66 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
70 * Audit policy string token table for au_poltostr() and au_strtopol().
77 static struct audit_polstr au_polstr[] = {
79 { AUDIT_AHLT, "ahlt" },
80 { AUDIT_ARGV, "argv" },
81 { AUDIT_ARGE, "arge" },
83 { AUDIT_WINDATA, "windata" },
84 { AUDIT_USER, "user" },
85 { AUDIT_GROUP, "group" },
86 { AUDIT_TRAIL, "trail" },
87 { AUDIT_PATH, "path" },
88 { AUDIT_SCNT, "scnt" },
89 { AUDIT_PUBLIC, "public" },
90 { AUDIT_ZONENAME, "zonename" },
91 { AUDIT_PERZONE, "perzone" },
96 * Returns the string value corresponding to the given label from the
99 * Must be called with mutex held.
102 getstrfromtype_locked(const char *name, char **str)
110 if ((fp == NULL) && ((fp = fopen(AUDIT_CONTROL_FILE, "r")) == NULL))
111 return (-1); /* Error */
114 if (fgets(linestr, AU_LINE_MAX, fp) == NULL) {
117 return (0); /* EOF */
120 if (linestr[0] == '#')
123 /* Remove trailing new line character and white space. */
124 nl = strchr(linestr, '\0') - 1;
125 while (nl >= linestr && ('\n' == *nl || ' ' == *nl ||
132 if ((type = strtok_r(tokptr, delim, &last)) != NULL) {
133 if (strcmp(name, type) == 0) {
134 /* Found matching name. */
135 *str = strtok_r(NULL, delim, &last);
138 return (-1); /* Parse error in file */
140 return (0); /* Success */
147 * Convert a given time value with a multiplier (seconds, hours, days, years) to
148 * seconds. Return 0 on success.
151 au_timetosec(time_t *seconds, u_long value, char mult)
159 *seconds = (time_t)value;
164 *seconds = (time_t)value * 60 * 60;
169 *seconds = (time_t)value * 60 * 60 * 24;
173 /* years. Add a day for each 4th (leap) year. */
174 *seconds = (time_t)value * 60 * 60 * 24 * 364 +
175 ((time_t)value / 4) * 60 * 60 * 24;
185 * Convert a given disk space value with a multiplier (bytes, kilobytes,
186 * megabytes, gigabytes) to bytes. Return 0 on success.
189 au_spacetobytes(size_t *bytes, u_long value, char mult)
198 *bytes = (size_t)value;
203 *bytes = (size_t)value * 1024;
208 *bytes = (size_t)value * 1024 * 1024;
213 *bytes = (size_t)value * 1024 * 1024 * 1024;
223 * Convert a policy to a string. Return -1 on failure, or >= 0 representing
224 * the actual size of the string placed in the buffer (excluding terminating
228 au_poltostr(int policy, size_t maxsize, char *buf)
238 if (policy & au_polstr[i].ap_policy) {
239 if (!first && strlcat(buf, ",", maxsize) >= maxsize)
241 if (strlcat(buf, au_polstr[i].ap_str, maxsize) >=
246 } while (NULL != au_polstr[++i].ap_str);
248 return (strlen(buf));
252 * Convert a string to a policy. Return -1 on failure (with errno EINVAL,
253 * ENOMEM) or 0 on success.
256 au_strtopol(const char *polstr, int *policy)
263 buffer = strdup(polstr);
268 while ((string = strsep(&bufp, ",")) != NULL) {
272 if (strcmp(string, au_polstr[i].ap_str) == 0) {
273 *policy |= au_polstr[i].ap_policy;
277 } while (NULL != au_polstr[++i].ap_str);
290 * Rewind the file pointer to beginning.
295 static time_t lastctime = 0;
301 * Check to see if the file on disk has changed. If so,
302 * force a re-read of the file by closing it.
304 if (fstat(fileno(fp), &sbuf) < 0)
306 if (lastctime != sbuf.st_ctime) {
307 lastctime = sbuf.st_ctime;
314 fseek(fp, 0, SEEK_SET);
322 #ifdef HAVE_PTHREAD_MUTEX_LOCK
323 pthread_mutex_lock(&mutex);
326 #ifdef HAVE_PTHREAD_MUTEX_LOCK
327 pthread_mutex_unlock(&mutex);
332 * Close the audit_control file.
338 #ifdef HAVE_PTHREAD_MUTEX_LOCK
339 pthread_mutex_lock(&mutex);
346 #ifdef HAVE_PTHREAD_MUTEX_LOCK
347 pthread_mutex_unlock(&mutex);
352 * Return audit directory information from the audit control file.
355 getacdir(char *name, int len)
361 * Check if another function was called between successive calls to
364 #ifdef HAVE_PTHREAD_MUTEX_LOCK
365 pthread_mutex_lock(&mutex);
367 if (inacdir && ptrmoved) {
370 fseek(fp, 0, SEEK_SET);
373 if (getstrfromtype_locked(DIR_CONTROL_ENTRY, &dir) < 0) {
374 #ifdef HAVE_PTHREAD_MUTEX_LOCK
375 pthread_mutex_unlock(&mutex);
380 #ifdef HAVE_PTHREAD_MUTEX_LOCK
381 pthread_mutex_unlock(&mutex);
385 if (strlen(dir) >= (size_t)len) {
386 #ifdef HAVE_PTHREAD_MUTEX_LOCK
387 pthread_mutex_unlock(&mutex);
391 strlcpy(name, dir, len);
392 #ifdef HAVE_PTHREAD_MUTEX_LOCK
393 pthread_mutex_unlock(&mutex);
399 * Return 1 if dist value is set to 'yes' or 'on'.
400 * Return 0 if dist value is set to something else.
401 * Return negative value on error.
409 #ifdef HAVE_PTHREAD_MUTEX_LOCK
410 pthread_mutex_lock(&mutex);
413 if (getstrfromtype_locked(DIST_CONTROL_ENTRY, &str) < 0) {
414 #ifdef HAVE_PTHREAD_MUTEX_LOCK
415 pthread_mutex_unlock(&mutex);
420 #ifdef HAVE_PTHREAD_MUTEX_LOCK
421 pthread_mutex_unlock(&mutex);
425 if (strcasecmp(str, "on") == 0 || strcasecmp(str, "yes") == 0)
429 #ifdef HAVE_PTHREAD_MUTEX_LOCK
430 pthread_mutex_unlock(&mutex);
436 * Return the minimum free diskspace value from the audit control file.
439 getacmin(int *min_val)
443 #ifdef HAVE_PTHREAD_MUTEX_LOCK
444 pthread_mutex_lock(&mutex);
447 if (getstrfromtype_locked(MINFREE_CONTROL_ENTRY, &min) < 0) {
448 #ifdef HAVE_PTHREAD_MUTEX_LOCK
449 pthread_mutex_unlock(&mutex);
454 #ifdef HAVE_PTHREAD_MUTEX_LOCK
455 pthread_mutex_unlock(&mutex);
459 *min_val = atoi(min);
460 #ifdef HAVE_PTHREAD_MUTEX_LOCK
461 pthread_mutex_unlock(&mutex);
467 * Return the desired trail rotation size from the audit control file.
470 getacfilesz(size_t *filesz_val)
477 #ifdef HAVE_PTHREAD_MUTEX_LOCK
478 pthread_mutex_lock(&mutex);
481 if (getstrfromtype_locked(FILESZ_CONTROL_ENTRY, &str) < 0) {
482 #ifdef HAVE_PTHREAD_MUTEX_LOCK
483 pthread_mutex_unlock(&mutex);
488 #ifdef HAVE_PTHREAD_MUTEX_LOCK
489 pthread_mutex_unlock(&mutex);
495 /* Trim off any leading white space. */
496 while (*str == ' ' || *str == '\t')
499 nparsed = sscanf(str, "%ju%c", (uintmax_t *)&val, &mult);
503 /* If no multiplier then assume 'B' (bytes). */
507 if (au_spacetobytes(filesz_val, val, mult) == 0)
512 #ifdef HAVE_PTHREAD_MUTEX_LOCK
513 pthread_mutex_unlock(&mutex);
519 * The file size must either be 0 or >= MIN_AUDIT_FILE_SIZE. 0
520 * indicates no rotation size.
522 if (*filesz_val < 0 || (*filesz_val > 0 &&
523 *filesz_val < MIN_AUDIT_FILE_SIZE)) {
524 #ifdef HAVE_PTHREAD_MUTEX_LOCK
525 pthread_mutex_unlock(&mutex);
531 #ifdef HAVE_PTHREAD_MUTEX_LOCK
532 pthread_mutex_unlock(&mutex);
538 getaccommon(const char *name, char *auditstr, int len)
542 #ifdef HAVE_PTHREAD_MUTEX_LOCK
543 pthread_mutex_lock(&mutex);
546 if (getstrfromtype_locked(name, &str) < 0) {
547 #ifdef HAVE_PTHREAD_MUTEX_LOCK
548 pthread_mutex_unlock(&mutex);
553 #ifdef HAVE_PTHREAD_MUTEX_LOCK
554 pthread_mutex_unlock(&mutex);
558 if (strlen(str) >= (size_t)len) {
559 #ifdef HAVE_PTHREAD_MUTEX_LOCK
560 pthread_mutex_unlock(&mutex);
564 strlcpy(auditstr, str, len);
565 #ifdef HAVE_PTHREAD_MUTEX_LOCK
566 pthread_mutex_unlock(&mutex);
572 * Return the system audit value from the audit contol file.
575 getacflg(char *auditstr, int len)
578 return (getaccommon(FLAGS_CONTROL_ENTRY, auditstr, len));
582 * Return the non attributable flags from the audit contol file.
585 getacna(char *auditstr, int len)
588 return (getaccommon(NA_CONTROL_ENTRY, auditstr, len));
592 * Return the policy field from the audit control file.
595 getacpol(char *auditstr, size_t len)
598 return (getaccommon(POLICY_CONTROL_ENTRY, auditstr, len));
602 getachost(char *auditstr, size_t len)
605 return (getaccommon(HOST_CONTROL_ENTRY, auditstr, len));
609 * Set expiration conditions.
612 setexpirecond(time_t *age, size_t *size, u_long value, char mult)
615 if (isupper(mult) || ' ' == mult)
616 return (au_spacetobytes(size, value, mult));
618 return (au_timetosec(age, value, mult));
622 * Return the expire-after field from the audit control file.
625 getacexpire(int *andflg, time_t *age, size_t *size)
631 char andor[AU_LINE_MAX];
637 #ifdef HAVE_PTHREAD_MUTEX_LOCK
638 pthread_mutex_lock(&mutex);
641 if (getstrfromtype_locked(EXPIRE_AFTER_CONTROL_ENTRY, &str) < 0) {
642 #ifdef HAVE_PTHREAD_MUTEX_LOCK
643 pthread_mutex_unlock(&mutex);
648 #ifdef HAVE_PTHREAD_MUTEX_LOCK
649 pthread_mutex_unlock(&mutex);
654 /* First, trim off any leading white space. */
655 while (*str == ' ' || *str == '\t')
658 nparsed = sscanf(str, "%lu%c%[ \tadnorADNOR]%lu%c", &val1, &mult1,
659 andor, &val2, &mult2);
663 /* If no multiplier then assume 'B' (Bytes). */
667 /* One expiration condition. */
668 if (setexpirecond(age, size, val1, mult1) != 0) {
669 #ifdef HAVE_PTHREAD_MUTEX_LOCK
670 pthread_mutex_unlock(&mutex);
677 /* Two expiration conditions. */
678 if (setexpirecond(age, size, val1, mult1) != 0 ||
679 setexpirecond(age, size, val2, mult2) != 0) {
680 #ifdef HAVE_PTHREAD_MUTEX_LOCK
681 pthread_mutex_unlock(&mutex);
685 if (strcasestr(andor, "and") != NULL)
687 else if (strcasestr(andor, "or") != NULL)
690 #ifdef HAVE_PTHREAD_MUTEX_LOCK
691 pthread_mutex_unlock(&mutex);
698 #ifdef HAVE_PTHREAD_MUTEX_LOCK
699 pthread_mutex_unlock(&mutex);
704 #ifdef HAVE_PTHREAD_MUTEX_LOCK
705 pthread_mutex_unlock(&mutex);