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#34 $
33 #include <config/config.h>
35 #include <bsm/libbsm.h>
40 #ifdef HAVE_PTHREAD_MUTEX_LOCK
47 #include <compat/strlcat.h>
50 #include <compat/strlcpy.h>
56 * Parse the contents of the audit_control file to return the audit control
57 * parameters. These static fields are protected by 'mutex'.
59 static FILE *fp = NULL;
60 static char linestr[AU_LINE_MAX];
61 static char *delim = ":";
63 static char inacdir = 0;
64 static char ptrmoved = 0;
66 #ifdef HAVE_PTHREAD_MUTEX_LOCK
67 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
71 * Audit policy string token table for au_poltostr() and au_strtopol().
78 static struct audit_polstr au_polstr[] = {
80 { AUDIT_AHLT, "ahlt" },
81 { AUDIT_ARGV, "argv" },
82 { AUDIT_ARGE, "arge" },
84 { AUDIT_WINDATA, "windata" },
85 { AUDIT_USER, "user" },
86 { AUDIT_GROUP, "group" },
87 { AUDIT_TRAIL, "trail" },
88 { AUDIT_PATH, "path" },
89 { AUDIT_SCNT, "scnt" },
90 { AUDIT_PUBLIC, "public" },
91 { AUDIT_ZONENAME, "zonename" },
92 { AUDIT_PERZONE, "perzone" },
97 * Returns the string value corresponding to the given label from the
100 * Must be called with mutex held.
103 getstrfromtype_locked(char *name, char **str)
111 if ((fp == NULL) && ((fp = fopen(AUDIT_CONTROL_FILE, "r")) == NULL))
112 return (-1); /* Error */
115 if (fgets(linestr, AU_LINE_MAX, fp) == NULL) {
118 return (0); /* EOF */
121 if (linestr[0] == '#')
124 /* Remove trailing new line character and white space. */
125 nl = strchr(linestr, '\0') - 1;
126 while (nl >= linestr && ('\n' == *nl || ' ' == *nl ||
133 if ((type = strtok_r(tokptr, delim, &last)) != NULL) {
134 if (strcmp(name, type) == 0) {
135 /* Found matching name. */
136 *str = strtok_r(NULL, delim, &last);
139 return (-1); /* Parse error in file */
141 return (0); /* Success */
148 * Convert a given time value with a multiplier (seconds, hours, days, years) to
149 * seconds. Return 0 on success.
152 au_timetosec(time_t *seconds, u_long value, char mult)
160 *seconds = (time_t)value;
165 *seconds = (time_t)value * 60 * 60;
170 *seconds = (time_t)value * 60 * 60 * 24;
174 /* years. Add a day for each 4th (leap) year. */
175 *seconds = (time_t)value * 60 * 60 * 24 * 364 +
176 ((time_t)value / 4) * 60 * 60 * 24;
186 * Convert a given disk space value with a multiplier (bytes, kilobytes,
187 * megabytes, gigabytes) to bytes. Return 0 on success.
190 au_spacetobytes(size_t *bytes, u_long value, char mult)
199 *bytes = (size_t)value;
204 *bytes = (size_t)value * 1024;
209 *bytes = (size_t)value * 1024 * 1024;
214 *bytes = (size_t)value * 1024 * 1024 * 1024;
224 * Convert a policy to a string. Return -1 on failure, or >= 0 representing
225 * the actual size of the string placed in the buffer (excluding terminating
229 au_poltostr(int policy, size_t maxsize, char *buf)
239 if (policy & au_polstr[i].ap_policy) {
240 if (!first && strlcat(buf, ",", maxsize) >= maxsize)
242 if (strlcat(buf, au_polstr[i].ap_str, maxsize) >=
247 } while (NULL != au_polstr[++i].ap_str);
249 return (strlen(buf));
253 * Convert a string to a policy. Return -1 on failure (with errno EINVAL,
254 * ENOMEM) or 0 on success.
257 au_strtopol(const char *polstr, int *policy)
264 buffer = strdup(polstr);
269 while ((string = strsep(&bufp, ",")) != NULL) {
273 if (strcmp(string, au_polstr[i].ap_str) == 0) {
274 *policy |= au_polstr[i].ap_policy;
278 } while (NULL != au_polstr[++i].ap_str);
291 * Rewind the file pointer to beginning.
296 static time_t lastctime = 0;
302 * Check to see if the file on disk has changed. If so,
303 * force a re-read of the file by closing it.
305 if (fstat(fileno(fp), &sbuf) < 0)
307 if (lastctime != sbuf.st_ctime) {
308 lastctime = sbuf.st_ctime;
315 fseek(fp, 0, SEEK_SET);
323 #ifdef HAVE_PTHREAD_MUTEX_LOCK
324 pthread_mutex_lock(&mutex);
327 #ifdef HAVE_PTHREAD_MUTEX_LOCK
328 pthread_mutex_unlock(&mutex);
333 * Close the audit_control file.
339 #ifdef HAVE_PTHREAD_MUTEX_LOCK
340 pthread_mutex_lock(&mutex);
347 #ifdef HAVE_PTHREAD_MUTEX_LOCK
348 pthread_mutex_unlock(&mutex);
353 * Return audit directory information from the audit control file.
356 getacdir(char *name, int len)
362 * Check if another function was called between successive calls to
365 #ifdef HAVE_PTHREAD_MUTEX_LOCK
366 pthread_mutex_lock(&mutex);
368 if (inacdir && ptrmoved) {
371 fseek(fp, 0, SEEK_SET);
374 if (getstrfromtype_locked(DIR_CONTROL_ENTRY, &dir) < 0) {
375 #ifdef HAVE_PTHREAD_MUTEX_LOCK
376 pthread_mutex_unlock(&mutex);
381 #ifdef HAVE_PTHREAD_MUTEX_LOCK
382 pthread_mutex_unlock(&mutex);
386 if (strlen(dir) >= (size_t)len) {
387 #ifdef HAVE_PTHREAD_MUTEX_LOCK
388 pthread_mutex_unlock(&mutex);
392 strlcpy(name, dir, len);
393 #ifdef HAVE_PTHREAD_MUTEX_LOCK
394 pthread_mutex_unlock(&mutex);
400 * Return the minimum free diskspace value from the audit control file.
403 getacmin(int *min_val)
407 #ifdef HAVE_PTHREAD_MUTEX_LOCK
408 pthread_mutex_lock(&mutex);
411 if (getstrfromtype_locked(MINFREE_CONTROL_ENTRY, &min) < 0) {
412 #ifdef HAVE_PTHREAD_MUTEX_LOCK
413 pthread_mutex_unlock(&mutex);
418 #ifdef HAVE_PTHREAD_MUTEX_LOCK
419 pthread_mutex_unlock(&mutex);
423 *min_val = atoi(min);
424 #ifdef HAVE_PTHREAD_MUTEX_LOCK
425 pthread_mutex_unlock(&mutex);
431 * Return the desired trail rotation size from the audit control file.
434 getacfilesz(size_t *filesz_val)
441 #ifdef HAVE_PTHREAD_MUTEX_LOCK
442 pthread_mutex_lock(&mutex);
445 if (getstrfromtype_locked(FILESZ_CONTROL_ENTRY, &str) < 0) {
446 #ifdef HAVE_PTHREAD_MUTEX_LOCK
447 pthread_mutex_unlock(&mutex);
452 #ifdef HAVE_PTHREAD_MUTEX_LOCK
453 pthread_mutex_unlock(&mutex);
459 /* Trim off any leading white space. */
460 while (*str == ' ' || *str == '\t')
463 nparsed = sscanf(str, "%ju%c", (uintmax_t *)&val, &mult);
467 /* If no multiplier then assume 'B' (bytes). */
471 if (au_spacetobytes(filesz_val, val, mult) == 0)
476 #ifdef HAVE_PTHREAD_MUTEX_LOCK
477 pthread_mutex_unlock(&mutex);
483 * The file size must either be 0 or >= MIN_AUDIT_FILE_SIZE. 0
484 * indicates no rotation size.
486 if (*filesz_val < 0 || (*filesz_val > 0 &&
487 *filesz_val < MIN_AUDIT_FILE_SIZE)) {
488 #ifdef HAVE_PTHREAD_MUTEX_LOCK
489 pthread_mutex_unlock(&mutex);
495 #ifdef HAVE_PTHREAD_MUTEX_LOCK
496 pthread_mutex_unlock(&mutex);
502 * Return the system audit value from the audit contol file.
505 getacflg(char *auditstr, int len)
509 #ifdef HAVE_PTHREAD_MUTEX_LOCK
510 pthread_mutex_lock(&mutex);
513 if (getstrfromtype_locked(FLAGS_CONTROL_ENTRY, &str) < 0) {
514 #ifdef HAVE_PTHREAD_MUTEX_LOCK
515 pthread_mutex_unlock(&mutex);
520 #ifdef HAVE_PTHREAD_MUTEX_LOCK
521 pthread_mutex_unlock(&mutex);
525 if (strlen(str) >= (size_t)len) {
526 #ifdef HAVE_PTHREAD_MUTEX_LOCK
527 pthread_mutex_unlock(&mutex);
531 strlcpy(auditstr, str, len);
532 #ifdef HAVE_PTHREAD_MUTEX_LOCK
533 pthread_mutex_unlock(&mutex);
539 * Return the non attributable flags from the audit contol file.
542 getacna(char *auditstr, int len)
546 #ifdef HAVE_PTHREAD_MUTEX_LOCK
547 pthread_mutex_lock(&mutex);
550 if (getstrfromtype_locked(NA_CONTROL_ENTRY, &str) < 0) {
551 #ifdef HAVE_PTHREAD_MUTEX_LOCK
552 pthread_mutex_unlock(&mutex);
557 #ifdef HAVE_PTHREAD_MUTEX_LOCK
558 pthread_mutex_unlock(&mutex);
562 if (strlen(str) >= (size_t)len) {
563 #ifdef HAVE_PTHREAD_MUTEX_LOCK
564 pthread_mutex_unlock(&mutex);
568 strlcpy(auditstr, str, len);
569 #ifdef HAVE_PTHREAD_MUTEX_LOCK
570 pthread_mutex_unlock(&mutex);
576 * Return the policy field from the audit control file.
579 getacpol(char *auditstr, size_t len)
583 #ifdef HAVE_PTHREAD_MUTEX_LOCK
584 pthread_mutex_lock(&mutex);
587 if (getstrfromtype_locked(POLICY_CONTROL_ENTRY, &str) < 0) {
588 #ifdef HAVE_PTHREAD_MUTEX_LOCK
589 pthread_mutex_unlock(&mutex);
594 #ifdef HAVE_PTHREAD_MUTEX_LOCK
595 pthread_mutex_unlock(&mutex);
599 if (strlen(str) >= len) {
600 #ifdef HAVE_PTHREAD_MUTEX_LOCK
601 pthread_mutex_unlock(&mutex);
605 strlcpy(auditstr, str, len);
606 #ifdef HAVE_PTHREAD_MUTEX_LOCK
607 pthread_mutex_unlock(&mutex);
613 getachost(char *auditstr, size_t len)
617 #ifdef HAVE_PTHREAD_MUTEX_LOCK
618 pthread_mutex_lock(&mutex);
621 if (getstrfromtype_locked(AUDIT_HOST_CONTROL_ENTRY, &str) < 0) {
622 #ifdef HAVE_PTHREAD_MUTEX_LOCK
623 pthread_mutex_unlock(&mutex);
628 #ifdef HAVE_PTHREAD_MUTEX_LOCK
629 pthread_mutex_unlock(&mutex);
633 if (strlen(str) >= len) {
634 #ifdef HAVE_PTHREAD_MUTEX_LOCK
635 pthread_mutex_unlock(&mutex);
639 strlcpy(auditstr, str, len);
640 #ifdef HAVE_PTHREAD_MUTEX_LOCK
641 pthread_mutex_unlock(&mutex);
647 * Set expiration conditions.
650 setexpirecond(time_t *age, size_t *size, u_long value, char mult)
653 if (isupper(mult) || ' ' == mult)
654 return (au_spacetobytes(size, value, mult));
656 return (au_timetosec(age, value, mult));
660 * Return the expire-after field from the audit control file.
663 getacexpire(int *andflg, time_t *age, size_t *size)
669 char andor[AU_LINE_MAX];
675 #ifdef HAVE_PTHREAD_MUTEX_LOCK
676 pthread_mutex_lock(&mutex);
679 if (getstrfromtype_locked(EXPIRE_AFTER_CONTROL_ENTRY, &str) < 0) {
680 #ifdef HAVE_PTHREAD_MUTEX_LOCK
681 pthread_mutex_unlock(&mutex);
686 #ifdef HAVE_PTHREAD_MUTEX_LOCK
687 pthread_mutex_unlock(&mutex);
692 /* First, trim off any leading white space. */
693 while (*str == ' ' || *str == '\t')
696 nparsed = sscanf(str, "%lu%c%[ \tadnorADNOR]%lu%c", &val1, &mult1,
697 andor, &val2, &mult2);
701 /* If no multiplier then assume 'B' (Bytes). */
705 /* One expiration condition. */
706 if (setexpirecond(age, size, val1, mult1) != 0) {
707 #ifdef HAVE_PTHREAD_MUTEX_LOCK
708 pthread_mutex_unlock(&mutex);
715 /* Two expiration conditions. */
716 if (setexpirecond(age, size, val1, mult1) != 0 ||
717 setexpirecond(age, size, val2, mult2) != 0) {
718 #ifdef HAVE_PTHREAD_MUTEX_LOCK
719 pthread_mutex_unlock(&mutex);
723 if (strcasestr(andor, "and") != NULL)
725 else if (strcasestr(andor, "or") != NULL)
728 #ifdef HAVE_PTHREAD_MUTEX_LOCK
729 pthread_mutex_unlock(&mutex);
736 #ifdef HAVE_PTHREAD_MUTEX_LOCK
737 pthread_mutex_unlock(&mutex);
742 #ifdef HAVE_PTHREAD_MUTEX_LOCK
743 pthread_mutex_unlock(&mutex);