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.
30 * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_control.c#41 $
33 #include <config/config.h>
35 #include <bsm/libbsm.h>
41 #ifdef HAVE_PTHREAD_MUTEX_LOCK
48 #include <compat/strlcat.h>
51 #include <compat/strlcpy.h>
57 * Parse the contents of the audit_control file to return the audit control
58 * parameters. These static fields are protected by 'mutex'.
60 static FILE *fp = NULL;
61 static char linestr[AU_LINE_MAX];
62 static char *delim = ":";
64 static char inacdir = 0;
65 static char ptrmoved = 0;
67 #ifdef HAVE_PTHREAD_MUTEX_LOCK
68 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
72 * Audit policy string token table for au_poltostr() and au_strtopol().
79 static struct audit_polstr au_polstr[] = {
81 { AUDIT_AHLT, "ahlt" },
82 { AUDIT_ARGV, "argv" },
83 { AUDIT_ARGE, "arge" },
85 { AUDIT_WINDATA, "windata" },
86 { AUDIT_USER, "user" },
87 { AUDIT_GROUP, "group" },
88 { AUDIT_TRAIL, "trail" },
89 { AUDIT_PATH, "path" },
90 { AUDIT_SCNT, "scnt" },
91 { AUDIT_PUBLIC, "public" },
92 { AUDIT_ZONENAME, "zonename" },
93 { AUDIT_PERZONE, "perzone" },
98 * Returns the string value corresponding to the given label from the
101 * Must be called with mutex held.
104 getstrfromtype_locked(const char *name, char **str)
112 if ((fp == NULL) && ((fp = fopen(AUDIT_CONTROL_FILE, "r")) == NULL))
113 return (-1); /* Error */
116 if (fgets(linestr, AU_LINE_MAX, fp) == NULL) {
119 return (0); /* EOF */
122 if (linestr[0] == '#')
125 /* Remove trailing new line character and white space. */
126 nl = strchr(linestr, '\0') - 1;
127 while (nl >= linestr && ('\n' == *nl || ' ' == *nl ||
134 if ((type = strtok_r(tokptr, delim, &last)) != NULL) {
135 if (strcmp(name, type) == 0) {
136 /* Found matching name. */
137 *str = strtok_r(NULL, delim, &last);
140 return (-1); /* Parse error in file */
142 return (0); /* Success */
149 * Convert a given time value with a multiplier (seconds, hours, days, years) to
150 * seconds. Return 0 on success.
153 au_timetosec(time_t *seconds, u_long value, char mult)
161 *seconds = (time_t)value;
166 *seconds = (time_t)value * 60 * 60;
171 *seconds = (time_t)value * 60 * 60 * 24;
175 /* years. Add a day for each 4th (leap) year. */
176 *seconds = (time_t)value * 60 * 60 * 24 * 364 +
177 ((time_t)value / 4) * 60 * 60 * 24;
187 * Convert a given disk space value with a multiplier (bytes, kilobytes,
188 * megabytes, gigabytes) to bytes. Return 0 on success.
191 au_spacetobytes(size_t *bytes, u_long value, char mult)
200 *bytes = (size_t)value;
205 *bytes = (size_t)value * 1024;
210 *bytes = (size_t)value * 1024 * 1024;
215 *bytes = (size_t)value * 1024 * 1024 * 1024;
225 * Convert a policy to a string. Return -1 on failure, or >= 0 representing
226 * the actual size of the string placed in the buffer (excluding terminating
230 au_poltostr(int policy, size_t maxsize, char *buf)
240 if (policy & au_polstr[i].ap_policy) {
241 if (!first && strlcat(buf, ",", maxsize) >= maxsize)
243 if (strlcat(buf, au_polstr[i].ap_str, maxsize) >=
248 } while (NULL != au_polstr[++i].ap_str);
250 return (strlen(buf));
254 * Convert a string to a policy. Return -1 on failure (with errno EINVAL,
255 * ENOMEM) or 0 on success.
258 au_strtopol(const char *polstr, int *policy)
265 buffer = strdup(polstr);
270 while ((string = strsep(&bufp, ",")) != NULL) {
274 if (strcmp(string, au_polstr[i].ap_str) == 0) {
275 *policy |= au_polstr[i].ap_policy;
279 } while (NULL != au_polstr[++i].ap_str);
292 * Rewind the file pointer to beginning.
297 static time_t lastctime = 0;
303 * Check to see if the file on disk has changed. If so,
304 * force a re-read of the file by closing it.
306 if (fstat(fileno(fp), &sbuf) < 0)
308 if (lastctime != sbuf.st_ctime) {
309 lastctime = sbuf.st_ctime;
316 fseek(fp, 0, SEEK_SET);
324 #ifdef HAVE_PTHREAD_MUTEX_LOCK
325 pthread_mutex_lock(&mutex);
328 #ifdef HAVE_PTHREAD_MUTEX_LOCK
329 pthread_mutex_unlock(&mutex);
334 * Close the audit_control file.
340 #ifdef HAVE_PTHREAD_MUTEX_LOCK
341 pthread_mutex_lock(&mutex);
348 #ifdef HAVE_PTHREAD_MUTEX_LOCK
349 pthread_mutex_unlock(&mutex);
354 * Return audit directory information from the audit control file.
357 getacdir(char *name, int len)
363 * Check if another function was called between successive calls to
366 #ifdef HAVE_PTHREAD_MUTEX_LOCK
367 pthread_mutex_lock(&mutex);
369 if (inacdir && ptrmoved) {
372 fseek(fp, 0, SEEK_SET);
375 if (getstrfromtype_locked(DIR_CONTROL_ENTRY, &dir) < 0) {
376 #ifdef HAVE_PTHREAD_MUTEX_LOCK
377 pthread_mutex_unlock(&mutex);
382 #ifdef HAVE_PTHREAD_MUTEX_LOCK
383 pthread_mutex_unlock(&mutex);
387 if (strlen(dir) >= (size_t)len) {
388 #ifdef HAVE_PTHREAD_MUTEX_LOCK
389 pthread_mutex_unlock(&mutex);
393 strlcpy(name, dir, len);
394 #ifdef HAVE_PTHREAD_MUTEX_LOCK
395 pthread_mutex_unlock(&mutex);
401 * Return 1 if dist value is set to 'yes' or 'on'.
402 * Return 0 if dist value is set to something else.
403 * Return negative value on error.
411 #ifdef HAVE_PTHREAD_MUTEX_LOCK
412 pthread_mutex_lock(&mutex);
415 if (getstrfromtype_locked(DIST_CONTROL_ENTRY, &str) < 0) {
416 #ifdef HAVE_PTHREAD_MUTEX_LOCK
417 pthread_mutex_unlock(&mutex);
422 #ifdef HAVE_PTHREAD_MUTEX_LOCK
423 pthread_mutex_unlock(&mutex);
427 if (strcasecmp(str, "on") == 0 || strcasecmp(str, "yes") == 0)
431 #ifdef HAVE_PTHREAD_MUTEX_LOCK
432 pthread_mutex_unlock(&mutex);
438 * Return the minimum free diskspace value from the audit control file.
441 getacmin(int *min_val)
445 #ifdef HAVE_PTHREAD_MUTEX_LOCK
446 pthread_mutex_lock(&mutex);
449 if (getstrfromtype_locked(MINFREE_CONTROL_ENTRY, &min) < 0) {
450 #ifdef HAVE_PTHREAD_MUTEX_LOCK
451 pthread_mutex_unlock(&mutex);
456 #ifdef HAVE_PTHREAD_MUTEX_LOCK
457 pthread_mutex_unlock(&mutex);
461 *min_val = atoi(min);
462 #ifdef HAVE_PTHREAD_MUTEX_LOCK
463 pthread_mutex_unlock(&mutex);
469 * Return the desired trail rotation size from the audit control file.
472 getacfilesz(size_t *filesz_val)
479 #ifdef HAVE_PTHREAD_MUTEX_LOCK
480 pthread_mutex_lock(&mutex);
483 if (getstrfromtype_locked(FILESZ_CONTROL_ENTRY, &str) < 0) {
484 #ifdef HAVE_PTHREAD_MUTEX_LOCK
485 pthread_mutex_unlock(&mutex);
490 #ifdef HAVE_PTHREAD_MUTEX_LOCK
491 pthread_mutex_unlock(&mutex);
497 /* Trim off any leading white space. */
498 while (*str == ' ' || *str == '\t')
501 nparsed = sscanf(str, "%ju%c", (uintmax_t *)&val, &mult);
505 /* If no multiplier then assume 'B' (bytes). */
509 if (au_spacetobytes(filesz_val, val, mult) == 0)
514 #ifdef HAVE_PTHREAD_MUTEX_LOCK
515 pthread_mutex_unlock(&mutex);
521 * The file size must either be 0 or >= MIN_AUDIT_FILE_SIZE. 0
522 * indicates no rotation size.
524 if (*filesz_val < 0 || (*filesz_val > 0 &&
525 *filesz_val < MIN_AUDIT_FILE_SIZE)) {
526 #ifdef HAVE_PTHREAD_MUTEX_LOCK
527 pthread_mutex_unlock(&mutex);
533 #ifdef HAVE_PTHREAD_MUTEX_LOCK
534 pthread_mutex_unlock(&mutex);
540 getaccommon(const char *name, char *auditstr, int len)
544 #ifdef HAVE_PTHREAD_MUTEX_LOCK
545 pthread_mutex_lock(&mutex);
548 if (getstrfromtype_locked(name, &str) < 0) {
549 #ifdef HAVE_PTHREAD_MUTEX_LOCK
550 pthread_mutex_unlock(&mutex);
555 #ifdef HAVE_PTHREAD_MUTEX_LOCK
556 pthread_mutex_unlock(&mutex);
560 if (strlen(str) >= (size_t)len) {
561 #ifdef HAVE_PTHREAD_MUTEX_LOCK
562 pthread_mutex_unlock(&mutex);
566 strlcpy(auditstr, str, len);
567 #ifdef HAVE_PTHREAD_MUTEX_LOCK
568 pthread_mutex_unlock(&mutex);
574 * Return the system audit value from the audit contol file.
577 getacflg(char *auditstr, int len)
580 return (getaccommon(FLAGS_CONTROL_ENTRY, auditstr, len));
584 * Return the non attributable flags from the audit contol file.
587 getacna(char *auditstr, int len)
590 return (getaccommon(NA_CONTROL_ENTRY, auditstr, len));
594 * Return the policy field from the audit control file.
597 getacpol(char *auditstr, size_t len)
600 return (getaccommon(POLICY_CONTROL_ENTRY, auditstr, len));
604 getachost(char *auditstr, size_t len)
607 return (getaccommon(HOST_CONTROL_ENTRY, auditstr, len));
611 * Set expiration conditions.
614 setexpirecond(time_t *age, size_t *size, u_long value, char mult)
617 if (isupper(mult) || ' ' == mult)
618 return (au_spacetobytes(size, value, mult));
620 return (au_timetosec(age, value, mult));
624 * Return the expire-after field from the audit control file.
627 getacexpire(int *andflg, time_t *age, size_t *size)
633 char andor[AU_LINE_MAX];
639 #ifdef HAVE_PTHREAD_MUTEX_LOCK
640 pthread_mutex_lock(&mutex);
643 if (getstrfromtype_locked(EXPIRE_AFTER_CONTROL_ENTRY, &str) < 0) {
644 #ifdef HAVE_PTHREAD_MUTEX_LOCK
645 pthread_mutex_unlock(&mutex);
650 #ifdef HAVE_PTHREAD_MUTEX_LOCK
651 pthread_mutex_unlock(&mutex);
656 /* First, trim off any leading white space. */
657 while (*str == ' ' || *str == '\t')
660 nparsed = sscanf(str, "%lu%c%[ \tadnorADNOR]%lu%c", &val1, &mult1,
661 andor, &val2, &mult2);
665 /* If no multiplier then assume 'B' (Bytes). */
669 /* One expiration condition. */
670 if (setexpirecond(age, size, val1, mult1) != 0) {
671 #ifdef HAVE_PTHREAD_MUTEX_LOCK
672 pthread_mutex_unlock(&mutex);
679 /* Two expiration conditions. */
680 if (setexpirecond(age, size, val1, mult1) != 0 ||
681 setexpirecond(age, size, val2, mult2) != 0) {
682 #ifdef HAVE_PTHREAD_MUTEX_LOCK
683 pthread_mutex_unlock(&mutex);
687 if (strcasestr(andor, "and") != NULL)
689 else if (strcasestr(andor, "or") != NULL)
692 #ifdef HAVE_PTHREAD_MUTEX_LOCK
693 pthread_mutex_unlock(&mutex);
700 #ifdef HAVE_PTHREAD_MUTEX_LOCK
701 pthread_mutex_unlock(&mutex);
706 #ifdef HAVE_PTHREAD_MUTEX_LOCK
707 pthread_mutex_unlock(&mutex);