152267f74SRobert Watson /*-
206edd2f1SRobert Watson * Copyright (c) 2004, 2009 Apple Inc.
3*5e386598SRobert Watson * Copyright (c) 2006, 2016 Robert N. M. Watson
4ca0716f5SRobert Watson * All rights reserved.
5ca0716f5SRobert Watson *
6*5e386598SRobert Watson * Portions of this software were developed by BAE Systems, the University of
7*5e386598SRobert Watson * Cambridge Computer Laboratory, and Memorial University under DARPA/AFRL
8*5e386598SRobert Watson * contract FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent
9*5e386598SRobert Watson * Computing (TC) research program.
10*5e386598SRobert Watson *
11ca0716f5SRobert Watson * Redistribution and use in source and binary forms, with or without
12ca0716f5SRobert Watson * modification, are permitted provided that the following conditions
13ca0716f5SRobert Watson * are met:
14ca0716f5SRobert Watson * 1. Redistributions of source code must retain the above copyright
15ca0716f5SRobert Watson * notice, this list of conditions and the following disclaimer.
16ca0716f5SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright
17ca0716f5SRobert Watson * notice, this list of conditions and the following disclaimer in the
18ca0716f5SRobert Watson * documentation and/or other materials provided with the distribution.
1952267f74SRobert Watson * 3. Neither the name of Apple Inc. ("Apple") nor the names of
20ca0716f5SRobert Watson * its contributors may be used to endorse or promote products derived
21ca0716f5SRobert Watson * from this software without specific prior written permission.
22ca0716f5SRobert Watson *
23ca0716f5SRobert Watson * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
24ca0716f5SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ca0716f5SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ca0716f5SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
27ca0716f5SRobert Watson * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ca0716f5SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ca0716f5SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ca0716f5SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31ca0716f5SRobert Watson * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32ca0716f5SRobert Watson * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33ca0716f5SRobert Watson * POSSIBILITY OF SUCH DAMAGE.
34ca0716f5SRobert Watson */
35ca0716f5SRobert Watson
3652267f74SRobert Watson #include <config/config.h>
3752267f74SRobert Watson
38ca0716f5SRobert Watson #include <bsm/libbsm.h>
39ca0716f5SRobert Watson
4006edd2f1SRobert Watson #include <ctype.h>
41ca0716f5SRobert Watson #include <errno.h>
42ca0716f5SRobert Watson #include <string.h>
43aa772005SRobert Watson #include <strings.h>
447a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
45ca0716f5SRobert Watson #include <pthread.h>
467a0a89d2SRobert Watson #endif
47ca0716f5SRobert Watson #include <stdio.h>
48ca0716f5SRobert Watson #include <stdlib.h>
49ca0716f5SRobert Watson
50bb97b418SRobert Watson #ifndef HAVE_STRLCAT
51bb97b418SRobert Watson #include <compat/strlcat.h>
52bb97b418SRobert Watson #endif
5352267f74SRobert Watson #ifndef HAVE_STRLCPY
5452267f74SRobert Watson #include <compat/strlcpy.h>
5552267f74SRobert Watson #endif
56bb97b418SRobert Watson
57c0020399SRobert Watson #include <sys/stat.h>
58c0020399SRobert Watson
59ca0716f5SRobert Watson /*
60ca0716f5SRobert Watson * Parse the contents of the audit_control file to return the audit control
61bb97b418SRobert Watson * parameters. These static fields are protected by 'mutex'.
62ca0716f5SRobert Watson */
63ca0716f5SRobert Watson static FILE *fp = NULL;
64ca0716f5SRobert Watson static char linestr[AU_LINE_MAX];
65ca0716f5SRobert Watson static char *delim = ":";
66ca0716f5SRobert Watson
67ca0716f5SRobert Watson static char inacdir = 0;
68ca0716f5SRobert Watson static char ptrmoved = 0;
69ca0716f5SRobert Watson
707a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
71ca0716f5SRobert Watson static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
727a0a89d2SRobert Watson #endif
73ca0716f5SRobert Watson
74ca0716f5SRobert Watson /*
7506edd2f1SRobert Watson * Audit policy string token table for au_poltostr() and au_strtopol().
7606edd2f1SRobert Watson */
7706edd2f1SRobert Watson struct audit_polstr {
7806edd2f1SRobert Watson long ap_policy;
7906edd2f1SRobert Watson const char *ap_str;
8006edd2f1SRobert Watson };
8106edd2f1SRobert Watson
8206edd2f1SRobert Watson static struct audit_polstr au_polstr[] = {
8306edd2f1SRobert Watson { AUDIT_CNT, "cnt" },
8406edd2f1SRobert Watson { AUDIT_AHLT, "ahlt" },
8506edd2f1SRobert Watson { AUDIT_ARGV, "argv" },
8606edd2f1SRobert Watson { AUDIT_ARGE, "arge" },
8706edd2f1SRobert Watson { AUDIT_SEQ, "seq" },
8806edd2f1SRobert Watson { AUDIT_WINDATA, "windata" },
8906edd2f1SRobert Watson { AUDIT_USER, "user" },
9006edd2f1SRobert Watson { AUDIT_GROUP, "group" },
9106edd2f1SRobert Watson { AUDIT_TRAIL, "trail" },
9206edd2f1SRobert Watson { AUDIT_PATH, "path" },
9306edd2f1SRobert Watson { AUDIT_SCNT, "scnt" },
9406edd2f1SRobert Watson { AUDIT_PUBLIC, "public" },
9506edd2f1SRobert Watson { AUDIT_ZONENAME, "zonename" },
9606edd2f1SRobert Watson { AUDIT_PERZONE, "perzone" },
9706edd2f1SRobert Watson { -1, NULL }
9806edd2f1SRobert Watson };
9906edd2f1SRobert Watson
10006edd2f1SRobert Watson /*
101ca0716f5SRobert Watson * Returns the string value corresponding to the given label from the
102ca0716f5SRobert Watson * configuration file.
103ca0716f5SRobert Watson *
104ca0716f5SRobert Watson * Must be called with mutex held.
105ca0716f5SRobert Watson */
106ca0716f5SRobert Watson static int
getstrfromtype_locked(const char * name,char ** str)107aa772005SRobert Watson getstrfromtype_locked(const char *name, char **str)
108ca0716f5SRobert Watson {
109ca0716f5SRobert Watson char *type, *nl;
110ca0716f5SRobert Watson char *tokptr;
111ca0716f5SRobert Watson char *last;
112ca0716f5SRobert Watson
113ca0716f5SRobert Watson *str = NULL;
114ca0716f5SRobert Watson
115ca0716f5SRobert Watson if ((fp == NULL) && ((fp = fopen(AUDIT_CONTROL_FILE, "r")) == NULL))
116ca0716f5SRobert Watson return (-1); /* Error */
117ca0716f5SRobert Watson
118ca0716f5SRobert Watson while (1) {
119ca0716f5SRobert Watson if (fgets(linestr, AU_LINE_MAX, fp) == NULL) {
120ca0716f5SRobert Watson if (ferror(fp))
121ca0716f5SRobert Watson return (-1);
122ca0716f5SRobert Watson return (0); /* EOF */
123ca0716f5SRobert Watson }
124ca0716f5SRobert Watson
125ca0716f5SRobert Watson if (linestr[0] == '#')
126ca0716f5SRobert Watson continue;
127ca0716f5SRobert Watson
128597df30eSRobert Watson /* Remove trailing new line character and white space. */
129597df30eSRobert Watson nl = strchr(linestr, '\0') - 1;
130597df30eSRobert Watson while (nl >= linestr && ('\n' == *nl || ' ' == *nl ||
131597df30eSRobert Watson '\t' == *nl)) {
132ca0716f5SRobert Watson *nl = '\0';
133597df30eSRobert Watson nl--;
134597df30eSRobert Watson }
135ca0716f5SRobert Watson
136ca0716f5SRobert Watson tokptr = linestr;
137ca0716f5SRobert Watson if ((type = strtok_r(tokptr, delim, &last)) != NULL) {
138ca0716f5SRobert Watson if (strcmp(name, type) == 0) {
139ca0716f5SRobert Watson /* Found matching name. */
140*5e386598SRobert Watson *str = last;
141ca0716f5SRobert Watson return (0); /* Success */
142ca0716f5SRobert Watson }
143ca0716f5SRobert Watson }
144ca0716f5SRobert Watson }
145ca0716f5SRobert Watson }
146ca0716f5SRobert Watson
147ca0716f5SRobert Watson /*
14806edd2f1SRobert Watson * Convert a given time value with a multiplier (seconds, hours, days, years) to
14906edd2f1SRobert Watson * seconds. Return 0 on success.
15006edd2f1SRobert Watson */
15106edd2f1SRobert Watson static int
au_timetosec(time_t * seconds,u_long value,char mult)15206edd2f1SRobert Watson au_timetosec(time_t *seconds, u_long value, char mult)
15306edd2f1SRobert Watson {
15406edd2f1SRobert Watson if (NULL == seconds)
15506edd2f1SRobert Watson return (-1);
15606edd2f1SRobert Watson
15706edd2f1SRobert Watson switch(mult) {
15806edd2f1SRobert Watson case 's':
15906edd2f1SRobert Watson /* seconds */
16006edd2f1SRobert Watson *seconds = (time_t)value;
16106edd2f1SRobert Watson break;
16206edd2f1SRobert Watson
16306edd2f1SRobert Watson case 'h':
16406edd2f1SRobert Watson /* hours */
16506edd2f1SRobert Watson *seconds = (time_t)value * 60 * 60;
16606edd2f1SRobert Watson break;
16706edd2f1SRobert Watson
16806edd2f1SRobert Watson case 'd':
16906edd2f1SRobert Watson /* days */
17006edd2f1SRobert Watson *seconds = (time_t)value * 60 * 60 * 24;
17106edd2f1SRobert Watson break;
17206edd2f1SRobert Watson
17306edd2f1SRobert Watson case 'y':
17406edd2f1SRobert Watson /* years. Add a day for each 4th (leap) year. */
17506edd2f1SRobert Watson *seconds = (time_t)value * 60 * 60 * 24 * 364 +
17606edd2f1SRobert Watson ((time_t)value / 4) * 60 * 60 * 24;
17706edd2f1SRobert Watson break;
17806edd2f1SRobert Watson
17906edd2f1SRobert Watson default:
18006edd2f1SRobert Watson return (-1);
18106edd2f1SRobert Watson }
18206edd2f1SRobert Watson return (0);
18306edd2f1SRobert Watson }
18406edd2f1SRobert Watson
18506edd2f1SRobert Watson /*
18606edd2f1SRobert Watson * Convert a given disk space value with a multiplier (bytes, kilobytes,
18706edd2f1SRobert Watson * megabytes, gigabytes) to bytes. Return 0 on success.
18806edd2f1SRobert Watson */
18906edd2f1SRobert Watson static int
au_spacetobytes(size_t * bytes,u_long value,char mult)19006edd2f1SRobert Watson au_spacetobytes(size_t *bytes, u_long value, char mult)
19106edd2f1SRobert Watson {
19206edd2f1SRobert Watson if (NULL == bytes)
19306edd2f1SRobert Watson return (-1);
19406edd2f1SRobert Watson
19506edd2f1SRobert Watson switch(mult) {
19606edd2f1SRobert Watson case 'B':
19706edd2f1SRobert Watson case ' ':
19806edd2f1SRobert Watson /* Bytes */
19906edd2f1SRobert Watson *bytes = (size_t)value;
20006edd2f1SRobert Watson break;
20106edd2f1SRobert Watson
20206edd2f1SRobert Watson case 'K':
20306edd2f1SRobert Watson /* Kilobytes */
20406edd2f1SRobert Watson *bytes = (size_t)value * 1024;
20506edd2f1SRobert Watson break;
20606edd2f1SRobert Watson
20706edd2f1SRobert Watson case 'M':
20806edd2f1SRobert Watson /* Megabytes */
20906edd2f1SRobert Watson *bytes = (size_t)value * 1024 * 1024;
21006edd2f1SRobert Watson break;
21106edd2f1SRobert Watson
21206edd2f1SRobert Watson case 'G':
21306edd2f1SRobert Watson /* Gigabytes */
21406edd2f1SRobert Watson *bytes = (size_t)value * 1024 * 1024 * 1024;
21506edd2f1SRobert Watson break;
21606edd2f1SRobert Watson
21706edd2f1SRobert Watson default:
21806edd2f1SRobert Watson return (-1);
21906edd2f1SRobert Watson }
22006edd2f1SRobert Watson return (0);
22106edd2f1SRobert Watson }
22206edd2f1SRobert Watson
22306edd2f1SRobert Watson /*
224bb97b418SRobert Watson * Convert a policy to a string. Return -1 on failure, or >= 0 representing
225bb97b418SRobert Watson * the actual size of the string placed in the buffer (excluding terminating
226bb97b418SRobert Watson * nul).
227bb97b418SRobert Watson */
228bb97b418SRobert Watson ssize_t
au_poltostr(int policy,size_t maxsize,char * buf)229c0020399SRobert Watson au_poltostr(int policy, size_t maxsize, char *buf)
230bb97b418SRobert Watson {
23106edd2f1SRobert Watson int first = 1;
23206edd2f1SRobert Watson int i = 0;
233bb97b418SRobert Watson
234bb97b418SRobert Watson if (maxsize < 1)
235bb97b418SRobert Watson return (-1);
236bb97b418SRobert Watson buf[0] = '\0';
237bb97b418SRobert Watson
23806edd2f1SRobert Watson do {
23906edd2f1SRobert Watson if (policy & au_polstr[i].ap_policy) {
24006edd2f1SRobert Watson if (!first && strlcat(buf, ",", maxsize) >= maxsize)
24106edd2f1SRobert Watson return (-1);
24206edd2f1SRobert Watson if (strlcat(buf, au_polstr[i].ap_str, maxsize) >=
24306edd2f1SRobert Watson maxsize)
244bb97b418SRobert Watson return (-1);
245bb97b418SRobert Watson first = 0;
246bb97b418SRobert Watson }
24706edd2f1SRobert Watson } while (NULL != au_polstr[++i].ap_str);
24806edd2f1SRobert Watson
249bb97b418SRobert Watson return (strlen(buf));
250bb97b418SRobert Watson }
251bb97b418SRobert Watson
252bb97b418SRobert Watson /*
253bb97b418SRobert Watson * Convert a string to a policy. Return -1 on failure (with errno EINVAL,
254bb97b418SRobert Watson * ENOMEM) or 0 on success.
255bb97b418SRobert Watson */
256bb97b418SRobert Watson int
au_strtopol(const char * polstr,int * policy)257c0020399SRobert Watson au_strtopol(const char *polstr, int *policy)
258bb97b418SRobert Watson {
259bb97b418SRobert Watson char *bufp, *string;
260bb97b418SRobert Watson char *buffer;
26106edd2f1SRobert Watson int i, matched;
262bb97b418SRobert Watson
263bb97b418SRobert Watson *policy = 0;
264bb97b418SRobert Watson buffer = strdup(polstr);
265bb97b418SRobert Watson if (buffer == NULL)
266bb97b418SRobert Watson return (-1);
267bb97b418SRobert Watson
268bb97b418SRobert Watson bufp = buffer;
269bb97b418SRobert Watson while ((string = strsep(&bufp, ",")) != NULL) {
27006edd2f1SRobert Watson matched = i = 0;
27106edd2f1SRobert Watson
27206edd2f1SRobert Watson do {
27306edd2f1SRobert Watson if (strcmp(string, au_polstr[i].ap_str) == 0) {
27406edd2f1SRobert Watson *policy |= au_polstr[i].ap_policy;
27506edd2f1SRobert Watson matched = 1;
27606edd2f1SRobert Watson break;
27706edd2f1SRobert Watson }
27806edd2f1SRobert Watson } while (NULL != au_polstr[++i].ap_str);
27906edd2f1SRobert Watson
28006edd2f1SRobert Watson if (!matched) {
281bb97b418SRobert Watson free(buffer);
282bb97b418SRobert Watson errno = EINVAL;
283bb97b418SRobert Watson return (-1);
284bb97b418SRobert Watson }
285bb97b418SRobert Watson }
286bb97b418SRobert Watson free(buffer);
287bb97b418SRobert Watson return (0);
288bb97b418SRobert Watson }
289bb97b418SRobert Watson
290bb97b418SRobert Watson /*
291ca0716f5SRobert Watson * Rewind the file pointer to beginning.
292ca0716f5SRobert Watson */
293bb97b418SRobert Watson static void
setac_locked(void)294bb97b418SRobert Watson setac_locked(void)
295bb97b418SRobert Watson {
296c0020399SRobert Watson static time_t lastctime = 0;
297c0020399SRobert Watson struct stat sbuf;
298bb97b418SRobert Watson
299bb97b418SRobert Watson ptrmoved = 1;
300c0020399SRobert Watson if (fp != NULL) {
301c0020399SRobert Watson /*
302c0020399SRobert Watson * Check to see if the file on disk has changed. If so,
303c0020399SRobert Watson * force a re-read of the file by closing it.
304c0020399SRobert Watson */
305c0020399SRobert Watson if (fstat(fileno(fp), &sbuf) < 0)
306c0020399SRobert Watson goto closefp;
307c0020399SRobert Watson if (lastctime != sbuf.st_ctime) {
308c0020399SRobert Watson lastctime = sbuf.st_ctime;
309c0020399SRobert Watson closefp:
310c0020399SRobert Watson fclose(fp);
311c0020399SRobert Watson fp = NULL;
312c0020399SRobert Watson return;
313c0020399SRobert Watson }
314c0020399SRobert Watson
315bb97b418SRobert Watson fseek(fp, 0, SEEK_SET);
316bb97b418SRobert Watson }
317c0020399SRobert Watson }
318bb97b418SRobert Watson
319ca0716f5SRobert Watson void
setac(void)320ca0716f5SRobert Watson setac(void)
321ca0716f5SRobert Watson {
322ca0716f5SRobert Watson
3237a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
324ca0716f5SRobert Watson pthread_mutex_lock(&mutex);
3257a0a89d2SRobert Watson #endif
326bb97b418SRobert Watson setac_locked();
3277a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
328ca0716f5SRobert Watson pthread_mutex_unlock(&mutex);
3297a0a89d2SRobert Watson #endif
330ca0716f5SRobert Watson }
331ca0716f5SRobert Watson
332ca0716f5SRobert Watson /*
333bb97b418SRobert Watson * Close the audit_control file.
334ca0716f5SRobert Watson */
335ca0716f5SRobert Watson void
endac(void)336ca0716f5SRobert Watson endac(void)
337ca0716f5SRobert Watson {
338ca0716f5SRobert Watson
3397a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
340ca0716f5SRobert Watson pthread_mutex_lock(&mutex);
3417a0a89d2SRobert Watson #endif
342ca0716f5SRobert Watson ptrmoved = 1;
343ca0716f5SRobert Watson if (fp != NULL) {
344ca0716f5SRobert Watson fclose(fp);
345ca0716f5SRobert Watson fp = NULL;
346ca0716f5SRobert Watson }
3477a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
348ca0716f5SRobert Watson pthread_mutex_unlock(&mutex);
3497a0a89d2SRobert Watson #endif
350ca0716f5SRobert Watson }
351ca0716f5SRobert Watson
352ca0716f5SRobert Watson /*
353ca0716f5SRobert Watson * Return audit directory information from the audit control file.
354ca0716f5SRobert Watson */
355ca0716f5SRobert Watson int
getacdir(char * name,int len)356ca0716f5SRobert Watson getacdir(char *name, int len)
357ca0716f5SRobert Watson {
358ca0716f5SRobert Watson char *dir;
359ca0716f5SRobert Watson int ret = 0;
360ca0716f5SRobert Watson
361ca0716f5SRobert Watson /*
362bb97b418SRobert Watson * Check if another function was called between successive calls to
363bb97b418SRobert Watson * getacdir.
364ca0716f5SRobert Watson */
3657a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
366bb97b418SRobert Watson pthread_mutex_lock(&mutex);
3677a0a89d2SRobert Watson #endif
368ca0716f5SRobert Watson if (inacdir && ptrmoved) {
369ca0716f5SRobert Watson ptrmoved = 0;
370ca0716f5SRobert Watson if (fp != NULL)
371ca0716f5SRobert Watson fseek(fp, 0, SEEK_SET);
372ca0716f5SRobert Watson ret = 2;
373ca0716f5SRobert Watson }
374ca0716f5SRobert Watson if (getstrfromtype_locked(DIR_CONTROL_ENTRY, &dir) < 0) {
3757a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
376ca0716f5SRobert Watson pthread_mutex_unlock(&mutex);
3777a0a89d2SRobert Watson #endif
378ca0716f5SRobert Watson return (-2);
379ca0716f5SRobert Watson }
380bb97b418SRobert Watson if (dir == NULL) {
3817a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
382ca0716f5SRobert Watson pthread_mutex_unlock(&mutex);
3837a0a89d2SRobert Watson #endif
384ca0716f5SRobert Watson return (-1);
385bb97b418SRobert Watson }
38652267f74SRobert Watson if (strlen(dir) >= (size_t)len) {
3877a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
388bb97b418SRobert Watson pthread_mutex_unlock(&mutex);
3897a0a89d2SRobert Watson #endif
390ca0716f5SRobert Watson return (-3);
391bb97b418SRobert Watson }
39252267f74SRobert Watson strlcpy(name, dir, len);
3937a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
394bb97b418SRobert Watson pthread_mutex_unlock(&mutex);
3957a0a89d2SRobert Watson #endif
396ca0716f5SRobert Watson return (ret);
397ca0716f5SRobert Watson }
398ca0716f5SRobert Watson
399ca0716f5SRobert Watson /*
400aa772005SRobert Watson * Return 1 if dist value is set to 'yes' or 'on'.
401aa772005SRobert Watson * Return 0 if dist value is set to something else.
402aa772005SRobert Watson * Return negative value on error.
403aa772005SRobert Watson */
404aa772005SRobert Watson int
getacdist(void)405aa772005SRobert Watson getacdist(void)
406aa772005SRobert Watson {
407aa772005SRobert Watson char *str;
408aa772005SRobert Watson int ret;
409aa772005SRobert Watson
410aa772005SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
411aa772005SRobert Watson pthread_mutex_lock(&mutex);
412aa772005SRobert Watson #endif
413aa772005SRobert Watson setac_locked();
414aa772005SRobert Watson if (getstrfromtype_locked(DIST_CONTROL_ENTRY, &str) < 0) {
415aa772005SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
416aa772005SRobert Watson pthread_mutex_unlock(&mutex);
417aa772005SRobert Watson #endif
418aa772005SRobert Watson return (-2);
419aa772005SRobert Watson }
420aa772005SRobert Watson if (str == NULL) {
421aa772005SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
422aa772005SRobert Watson pthread_mutex_unlock(&mutex);
423aa772005SRobert Watson #endif
424aa772005SRobert Watson return (0);
425aa772005SRobert Watson }
426aa772005SRobert Watson if (strcasecmp(str, "on") == 0 || strcasecmp(str, "yes") == 0)
427aa772005SRobert Watson ret = 1;
428aa772005SRobert Watson else
429aa772005SRobert Watson ret = 0;
430aa772005SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
431aa772005SRobert Watson pthread_mutex_unlock(&mutex);
432aa772005SRobert Watson #endif
433aa772005SRobert Watson return (ret);
434aa772005SRobert Watson }
435aa772005SRobert Watson
436aa772005SRobert Watson /*
437bb97b418SRobert Watson * Return the minimum free diskspace value from the audit control file.
438ca0716f5SRobert Watson */
439ca0716f5SRobert Watson int
getacmin(int * min_val)440ca0716f5SRobert Watson getacmin(int *min_val)
441ca0716f5SRobert Watson {
442ca0716f5SRobert Watson char *min;
443ca0716f5SRobert Watson
4447a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
445ca0716f5SRobert Watson pthread_mutex_lock(&mutex);
4467a0a89d2SRobert Watson #endif
447bb97b418SRobert Watson setac_locked();
448ca0716f5SRobert Watson if (getstrfromtype_locked(MINFREE_CONTROL_ENTRY, &min) < 0) {
4497a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
450ca0716f5SRobert Watson pthread_mutex_unlock(&mutex);
4517a0a89d2SRobert Watson #endif
452ca0716f5SRobert Watson return (-2);
453ca0716f5SRobert Watson }
454bb97b418SRobert Watson if (min == NULL) {
4557a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
456ca0716f5SRobert Watson pthread_mutex_unlock(&mutex);
4577a0a89d2SRobert Watson #endif
458aa772005SRobert Watson return (-1);
459bb97b418SRobert Watson }
460ca0716f5SRobert Watson *min_val = atoi(min);
4617a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
462bb97b418SRobert Watson pthread_mutex_unlock(&mutex);
4637a0a89d2SRobert Watson #endif
464ca0716f5SRobert Watson return (0);
465ca0716f5SRobert Watson }
466ca0716f5SRobert Watson
467ca0716f5SRobert Watson /*
4684bd0c025SRobert Watson * Return the desired trail rotation size from the audit control file.
4694bd0c025SRobert Watson */
4704bd0c025SRobert Watson int
getacfilesz(size_t * filesz_val)4714bd0c025SRobert Watson getacfilesz(size_t *filesz_val)
4724bd0c025SRobert Watson {
47306edd2f1SRobert Watson char *str;
47406edd2f1SRobert Watson size_t val;
47506edd2f1SRobert Watson char mult;
47606edd2f1SRobert Watson int nparsed;
4774bd0c025SRobert Watson
4787a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
4794bd0c025SRobert Watson pthread_mutex_lock(&mutex);
4807a0a89d2SRobert Watson #endif
4814bd0c025SRobert Watson setac_locked();
48206edd2f1SRobert Watson if (getstrfromtype_locked(FILESZ_CONTROL_ENTRY, &str) < 0) {
4837a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
4844bd0c025SRobert Watson pthread_mutex_unlock(&mutex);
4857a0a89d2SRobert Watson #endif
4864bd0c025SRobert Watson return (-2);
4874bd0c025SRobert Watson }
48806edd2f1SRobert Watson if (str == NULL) {
4897a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
4904bd0c025SRobert Watson pthread_mutex_unlock(&mutex);
4917a0a89d2SRobert Watson #endif
4924bd0c025SRobert Watson errno = EINVAL;
493aa772005SRobert Watson return (-1);
4944bd0c025SRobert Watson }
49506edd2f1SRobert Watson
49606edd2f1SRobert Watson /* Trim off any leading white space. */
49706edd2f1SRobert Watson while (*str == ' ' || *str == '\t')
49806edd2f1SRobert Watson str++;
49906edd2f1SRobert Watson
50006edd2f1SRobert Watson nparsed = sscanf(str, "%ju%c", (uintmax_t *)&val, &mult);
50106edd2f1SRobert Watson
50206edd2f1SRobert Watson switch (nparsed) {
50306edd2f1SRobert Watson case 1:
50406edd2f1SRobert Watson /* If no multiplier then assume 'B' (bytes). */
50506edd2f1SRobert Watson mult = 'B';
50606edd2f1SRobert Watson /* fall through */
50706edd2f1SRobert Watson case 2:
50806edd2f1SRobert Watson if (au_spacetobytes(filesz_val, val, mult) == 0)
50906edd2f1SRobert Watson break;
51006edd2f1SRobert Watson /* fall through */
51106edd2f1SRobert Watson default:
51206edd2f1SRobert Watson errno = EINVAL;
5137a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
5144bd0c025SRobert Watson pthread_mutex_unlock(&mutex);
5157a0a89d2SRobert Watson #endif
5164bd0c025SRobert Watson return (-1);
5174bd0c025SRobert Watson }
51806edd2f1SRobert Watson
5194bd0c025SRobert Watson /*
5204bd0c025SRobert Watson * The file size must either be 0 or >= MIN_AUDIT_FILE_SIZE. 0
5214bd0c025SRobert Watson * indicates no rotation size.
5224bd0c025SRobert Watson */
52306edd2f1SRobert Watson if (*filesz_val < 0 || (*filesz_val > 0 &&
52406edd2f1SRobert Watson *filesz_val < MIN_AUDIT_FILE_SIZE)) {
5257a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
5264bd0c025SRobert Watson pthread_mutex_unlock(&mutex);
5277a0a89d2SRobert Watson #endif
52806edd2f1SRobert Watson filesz_val = 0L;
5294bd0c025SRobert Watson errno = EINVAL;
5304bd0c025SRobert Watson return (-1);
5314bd0c025SRobert Watson }
5327a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
5334bd0c025SRobert Watson pthread_mutex_unlock(&mutex);
5347a0a89d2SRobert Watson #endif
5354bd0c025SRobert Watson return (0);
5364bd0c025SRobert Watson }
5374bd0c025SRobert Watson
538aa772005SRobert Watson static int
getaccommon(const char * name,char * auditstr,int len)539aa772005SRobert Watson getaccommon(const char *name, char *auditstr, int len)
540ca0716f5SRobert Watson {
541ca0716f5SRobert Watson char *str;
542ca0716f5SRobert Watson
5437a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
544ca0716f5SRobert Watson pthread_mutex_lock(&mutex);
5457a0a89d2SRobert Watson #endif
546bb97b418SRobert Watson setac_locked();
547aa772005SRobert Watson if (getstrfromtype_locked(name, &str) < 0) {
5487a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
549bb97b418SRobert Watson pthread_mutex_unlock(&mutex);
5507a0a89d2SRobert Watson #endif
551bb97b418SRobert Watson return (-2);
552bb97b418SRobert Watson }
553*5e386598SRobert Watson
554*5e386598SRobert Watson /*
555*5e386598SRobert Watson * getstrfromtype_locked() can return NULL for an empty value -- make
556*5e386598SRobert Watson * sure to handle this by coercing the NULL back into an empty string.
557*5e386598SRobert Watson */
558*5e386598SRobert Watson if (str != NULL && (strlen(str) >= (size_t)len)) {
5597a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
560bb97b418SRobert Watson pthread_mutex_unlock(&mutex);
5617a0a89d2SRobert Watson #endif
562bb97b418SRobert Watson return (-3);
563bb97b418SRobert Watson }
564*5e386598SRobert Watson strlcpy(auditstr, str != NULL ? str : "", len);
5657a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
56652267f74SRobert Watson pthread_mutex_unlock(&mutex);
5677a0a89d2SRobert Watson #endif
56852267f74SRobert Watson return (0);
56952267f74SRobert Watson }
57052267f74SRobert Watson
571aa772005SRobert Watson /*
572aa772005SRobert Watson * Return the system audit value from the audit contol file.
573aa772005SRobert Watson */
574aa772005SRobert Watson int
getacflg(char * auditstr,int len)575aa772005SRobert Watson getacflg(char *auditstr, int len)
576aa772005SRobert Watson {
577aa772005SRobert Watson
578aa772005SRobert Watson return (getaccommon(FLAGS_CONTROL_ENTRY, auditstr, len));
579aa772005SRobert Watson }
580aa772005SRobert Watson
581aa772005SRobert Watson /*
582aa772005SRobert Watson * Return the non attributable flags from the audit contol file.
583aa772005SRobert Watson */
584aa772005SRobert Watson int
getacna(char * auditstr,int len)585aa772005SRobert Watson getacna(char *auditstr, int len)
586aa772005SRobert Watson {
587aa772005SRobert Watson
588aa772005SRobert Watson return (getaccommon(NA_CONTROL_ENTRY, auditstr, len));
589aa772005SRobert Watson }
590aa772005SRobert Watson
591aa772005SRobert Watson /*
592aa772005SRobert Watson * Return the policy field from the audit control file.
593aa772005SRobert Watson */
594aa772005SRobert Watson int
getacpol(char * auditstr,size_t len)595aa772005SRobert Watson getacpol(char *auditstr, size_t len)
596aa772005SRobert Watson {
597aa772005SRobert Watson
598aa772005SRobert Watson return (getaccommon(POLICY_CONTROL_ENTRY, auditstr, len));
599aa772005SRobert Watson }
600aa772005SRobert Watson
60152267f74SRobert Watson int
getachost(char * auditstr,size_t len)60252267f74SRobert Watson getachost(char *auditstr, size_t len)
60352267f74SRobert Watson {
60452267f74SRobert Watson
605aa772005SRobert Watson return (getaccommon(HOST_CONTROL_ENTRY, auditstr, len));
60606edd2f1SRobert Watson }
60706edd2f1SRobert Watson
60806edd2f1SRobert Watson /*
60906edd2f1SRobert Watson * Set expiration conditions.
61006edd2f1SRobert Watson */
61106edd2f1SRobert Watson static int
setexpirecond(time_t * age,size_t * size,u_long value,char mult)61206edd2f1SRobert Watson setexpirecond(time_t *age, size_t *size, u_long value, char mult)
61306edd2f1SRobert Watson {
61406edd2f1SRobert Watson
61506edd2f1SRobert Watson if (isupper(mult) || ' ' == mult)
61606edd2f1SRobert Watson return (au_spacetobytes(size, value, mult));
61706edd2f1SRobert Watson else
61806edd2f1SRobert Watson return (au_timetosec(age, value, mult));
61906edd2f1SRobert Watson }
62006edd2f1SRobert Watson
62106edd2f1SRobert Watson /*
62206edd2f1SRobert Watson * Return the expire-after field from the audit control file.
62306edd2f1SRobert Watson */
62406edd2f1SRobert Watson int
getacexpire(int * andflg,time_t * age,size_t * size)62506edd2f1SRobert Watson getacexpire(int *andflg, time_t *age, size_t *size)
62606edd2f1SRobert Watson {
62706edd2f1SRobert Watson char *str;
62806edd2f1SRobert Watson int nparsed;
62906edd2f1SRobert Watson u_long val1, val2;
63006edd2f1SRobert Watson char mult1, mult2;
63106edd2f1SRobert Watson char andor[AU_LINE_MAX];
63206edd2f1SRobert Watson
63306edd2f1SRobert Watson *age = 0L;
63406edd2f1SRobert Watson *size = 0LL;
63506edd2f1SRobert Watson *andflg = 0;
63606edd2f1SRobert Watson
63706edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
63806edd2f1SRobert Watson pthread_mutex_lock(&mutex);
63906edd2f1SRobert Watson #endif
64006edd2f1SRobert Watson setac_locked();
64106edd2f1SRobert Watson if (getstrfromtype_locked(EXPIRE_AFTER_CONTROL_ENTRY, &str) < 0) {
64206edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
64306edd2f1SRobert Watson pthread_mutex_unlock(&mutex);
64406edd2f1SRobert Watson #endif
64506edd2f1SRobert Watson return (-2);
64606edd2f1SRobert Watson }
64706edd2f1SRobert Watson if (str == NULL) {
64806edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
64906edd2f1SRobert Watson pthread_mutex_unlock(&mutex);
65006edd2f1SRobert Watson #endif
651aa772005SRobert Watson return (-1);
65206edd2f1SRobert Watson }
65306edd2f1SRobert Watson
65406edd2f1SRobert Watson /* First, trim off any leading white space. */
65506edd2f1SRobert Watson while (*str == ' ' || *str == '\t')
65606edd2f1SRobert Watson str++;
65706edd2f1SRobert Watson
65806edd2f1SRobert Watson nparsed = sscanf(str, "%lu%c%[ \tadnorADNOR]%lu%c", &val1, &mult1,
65906edd2f1SRobert Watson andor, &val2, &mult2);
66006edd2f1SRobert Watson
66106edd2f1SRobert Watson switch (nparsed) {
66206edd2f1SRobert Watson case 1:
66306edd2f1SRobert Watson /* If no multiplier then assume 'B' (Bytes). */
66406edd2f1SRobert Watson mult1 = 'B';
66506edd2f1SRobert Watson /* fall through */
66606edd2f1SRobert Watson case 2:
66706edd2f1SRobert Watson /* One expiration condition. */
66806edd2f1SRobert Watson if (setexpirecond(age, size, val1, mult1) != 0) {
66906edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
67006edd2f1SRobert Watson pthread_mutex_unlock(&mutex);
67106edd2f1SRobert Watson #endif
67206edd2f1SRobert Watson return (-1);
67306edd2f1SRobert Watson }
67406edd2f1SRobert Watson break;
67506edd2f1SRobert Watson
67606edd2f1SRobert Watson case 5:
67706edd2f1SRobert Watson /* Two expiration conditions. */
67806edd2f1SRobert Watson if (setexpirecond(age, size, val1, mult1) != 0 ||
67906edd2f1SRobert Watson setexpirecond(age, size, val2, mult2) != 0) {
68006edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
68106edd2f1SRobert Watson pthread_mutex_unlock(&mutex);
68206edd2f1SRobert Watson #endif
68306edd2f1SRobert Watson return (-1);
68406edd2f1SRobert Watson }
68506edd2f1SRobert Watson if (strcasestr(andor, "and") != NULL)
68606edd2f1SRobert Watson *andflg = 1;
68706edd2f1SRobert Watson else if (strcasestr(andor, "or") != NULL)
68806edd2f1SRobert Watson *andflg = 0;
68906edd2f1SRobert Watson else {
69006edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
69106edd2f1SRobert Watson pthread_mutex_unlock(&mutex);
69206edd2f1SRobert Watson #endif
69306edd2f1SRobert Watson return (-1);
69406edd2f1SRobert Watson }
69506edd2f1SRobert Watson break;
69606edd2f1SRobert Watson
69706edd2f1SRobert Watson default:
69806edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
69906edd2f1SRobert Watson pthread_mutex_unlock(&mutex);
70006edd2f1SRobert Watson #endif
70106edd2f1SRobert Watson return (-1);
70206edd2f1SRobert Watson }
70306edd2f1SRobert Watson
7047a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
705bb97b418SRobert Watson pthread_mutex_unlock(&mutex);
7067a0a89d2SRobert Watson #endif
707ca0716f5SRobert Watson return (0);
708ca0716f5SRobert Watson }
709*5e386598SRobert Watson /*
710*5e386598SRobert Watson * Return the desired queue size from the audit control file.
711*5e386598SRobert Watson */
712*5e386598SRobert Watson int
getacqsize(int * qsz_val)713*5e386598SRobert Watson getacqsize(int *qsz_val)
714*5e386598SRobert Watson {
715*5e386598SRobert Watson char *str;
716*5e386598SRobert Watson int nparsed;
717*5e386598SRobert Watson
718*5e386598SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
719*5e386598SRobert Watson pthread_mutex_lock(&mutex);
720*5e386598SRobert Watson #endif
721*5e386598SRobert Watson setac_locked();
722*5e386598SRobert Watson if (getstrfromtype_locked(QSZ_CONTROL_ENTRY, &str) < 0) {
723*5e386598SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
724*5e386598SRobert Watson pthread_mutex_unlock(&mutex);
725*5e386598SRobert Watson #endif
726*5e386598SRobert Watson return (-2);
727*5e386598SRobert Watson }
728*5e386598SRobert Watson if (str == NULL) {
729*5e386598SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
730*5e386598SRobert Watson pthread_mutex_unlock(&mutex);
731*5e386598SRobert Watson #endif
732*5e386598SRobert Watson *qsz_val = USE_DEFAULT_QSZ;
733*5e386598SRobert Watson return (0);
734*5e386598SRobert Watson }
735*5e386598SRobert Watson
736*5e386598SRobert Watson /* Trim off any leading white space. */
737*5e386598SRobert Watson while (*str == ' ' || *str == '\t')
738*5e386598SRobert Watson str++;
739*5e386598SRobert Watson
740*5e386598SRobert Watson nparsed = sscanf(str, "%d", (int *)qsz_val);
741*5e386598SRobert Watson
742*5e386598SRobert Watson if (nparsed != 1) {
743*5e386598SRobert Watson errno = EINVAL;
744*5e386598SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
745*5e386598SRobert Watson pthread_mutex_unlock(&mutex);
746*5e386598SRobert Watson #endif
747*5e386598SRobert Watson return (-1);
748*5e386598SRobert Watson }
749*5e386598SRobert Watson
750*5e386598SRobert Watson /* The queue size must either be 0 or < AQ_MAXHIGH */
751*5e386598SRobert Watson if (*qsz_val < 0 || *qsz_val > AQ_MAXHIGH) {
752*5e386598SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
753*5e386598SRobert Watson pthread_mutex_unlock(&mutex);
754*5e386598SRobert Watson #endif
755*5e386598SRobert Watson qsz_val = 0L;
756*5e386598SRobert Watson errno = EINVAL;
757*5e386598SRobert Watson return (-1);
758*5e386598SRobert Watson }
759*5e386598SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
760*5e386598SRobert Watson pthread_mutex_unlock(&mutex);
761*5e386598SRobert Watson #endif
762*5e386598SRobert Watson return (0);
763*5e386598SRobert Watson }
764