xref: /freebsd/contrib/openbsm/libbsm/bsm_control.c (revision 5e386598a6d77973b93c073080f0cc574edda9e2)
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