xref: /freebsd/contrib/openbsm/libbsm/bsm_control.c (revision 597df30e62c04ff3e8d1e03f997b67427494a5cd)
152267f74SRobert Watson /*-
206edd2f1SRobert Watson  * Copyright (c) 2004, 2009 Apple Inc.
3bb97b418SRobert Watson  * Copyright (c) 2006 Robert N. M. Watson
4ca0716f5SRobert Watson  * All rights reserved.
5ca0716f5SRobert Watson  *
6ca0716f5SRobert Watson  * Redistribution and use in source and binary forms, with or without
7ca0716f5SRobert Watson  * modification, are permitted provided that the following conditions
8ca0716f5SRobert Watson  * are met:
9ca0716f5SRobert Watson  * 1.  Redistributions of source code must retain the above copyright
10ca0716f5SRobert Watson  *     notice, this list of conditions and the following disclaimer.
11ca0716f5SRobert Watson  * 2.  Redistributions in binary form must reproduce the above copyright
12ca0716f5SRobert Watson  *     notice, this list of conditions and the following disclaimer in the
13ca0716f5SRobert Watson  *     documentation and/or other materials provided with the distribution.
1452267f74SRobert Watson  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
15ca0716f5SRobert Watson  *     its contributors may be used to endorse or promote products derived
16ca0716f5SRobert Watson  *     from this software without specific prior written permission.
17ca0716f5SRobert Watson  *
18ca0716f5SRobert Watson  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
19ca0716f5SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20ca0716f5SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21ca0716f5SRobert Watson  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
22ca0716f5SRobert Watson  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23ca0716f5SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24ca0716f5SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25ca0716f5SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26ca0716f5SRobert Watson  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27ca0716f5SRobert Watson  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28ca0716f5SRobert Watson  * POSSIBILITY OF SUCH DAMAGE.
29ca0716f5SRobert Watson  *
30597df30eSRobert Watson  * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_control.c#34 $
31ca0716f5SRobert Watson  */
32ca0716f5SRobert Watson 
3352267f74SRobert Watson #include <config/config.h>
3452267f74SRobert Watson 
35ca0716f5SRobert Watson #include <bsm/libbsm.h>
36ca0716f5SRobert Watson 
3706edd2f1SRobert Watson #include <ctype.h>
38ca0716f5SRobert Watson #include <errno.h>
39ca0716f5SRobert Watson #include <string.h>
407a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
41ca0716f5SRobert Watson #include <pthread.h>
427a0a89d2SRobert Watson #endif
43ca0716f5SRobert Watson #include <stdio.h>
44ca0716f5SRobert Watson #include <stdlib.h>
45ca0716f5SRobert Watson 
46bb97b418SRobert Watson #ifndef HAVE_STRLCAT
47bb97b418SRobert Watson #include <compat/strlcat.h>
48bb97b418SRobert Watson #endif
4952267f74SRobert Watson #ifndef HAVE_STRLCPY
5052267f74SRobert Watson #include <compat/strlcpy.h>
5152267f74SRobert Watson #endif
52bb97b418SRobert Watson 
53c0020399SRobert Watson #include <sys/stat.h>
54c0020399SRobert Watson 
55ca0716f5SRobert Watson /*
56ca0716f5SRobert Watson  * Parse the contents of the audit_control file to return the audit control
57bb97b418SRobert Watson  * parameters.  These static fields are protected by 'mutex'.
58ca0716f5SRobert Watson  */
59ca0716f5SRobert Watson static FILE	*fp = NULL;
60ca0716f5SRobert Watson static char	linestr[AU_LINE_MAX];
61ca0716f5SRobert Watson static char	*delim = ":";
62ca0716f5SRobert Watson 
63ca0716f5SRobert Watson static char	inacdir = 0;
64ca0716f5SRobert Watson static char	ptrmoved = 0;
65ca0716f5SRobert Watson 
667a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
67ca0716f5SRobert Watson static pthread_mutex_t	mutex = PTHREAD_MUTEX_INITIALIZER;
687a0a89d2SRobert Watson #endif
69ca0716f5SRobert Watson 
70ca0716f5SRobert Watson /*
7106edd2f1SRobert Watson  * Audit policy string token table for au_poltostr() and au_strtopol().
7206edd2f1SRobert Watson  */
7306edd2f1SRobert Watson struct audit_polstr {
7406edd2f1SRobert Watson 	long 		 ap_policy;
7506edd2f1SRobert Watson 	const char 	*ap_str;
7606edd2f1SRobert Watson };
7706edd2f1SRobert Watson 
7806edd2f1SRobert Watson static struct audit_polstr au_polstr[] = {
7906edd2f1SRobert Watson 	{ AUDIT_CNT,		"cnt"		},
8006edd2f1SRobert Watson 	{ AUDIT_AHLT,		"ahlt"		},
8106edd2f1SRobert Watson 	{ AUDIT_ARGV,		"argv"		},
8206edd2f1SRobert Watson 	{ AUDIT_ARGE,		"arge"		},
8306edd2f1SRobert Watson 	{ AUDIT_SEQ,		"seq"		},
8406edd2f1SRobert Watson 	{ AUDIT_WINDATA,	"windata"	},
8506edd2f1SRobert Watson 	{ AUDIT_USER,		"user"		},
8606edd2f1SRobert Watson 	{ AUDIT_GROUP,		"group"		},
8706edd2f1SRobert Watson 	{ AUDIT_TRAIL,		"trail"		},
8806edd2f1SRobert Watson 	{ AUDIT_PATH,		"path"		},
8906edd2f1SRobert Watson 	{ AUDIT_SCNT,		"scnt"		},
9006edd2f1SRobert Watson 	{ AUDIT_PUBLIC,		"public"	},
9106edd2f1SRobert Watson 	{ AUDIT_ZONENAME,	"zonename"	},
9206edd2f1SRobert Watson 	{ AUDIT_PERZONE,	"perzone"	},
9306edd2f1SRobert Watson 	{ -1,			NULL		}
9406edd2f1SRobert Watson };
9506edd2f1SRobert Watson 
9606edd2f1SRobert Watson /*
97ca0716f5SRobert Watson  * Returns the string value corresponding to the given label from the
98ca0716f5SRobert Watson  * configuration file.
99ca0716f5SRobert Watson  *
100ca0716f5SRobert Watson  * Must be called with mutex held.
101ca0716f5SRobert Watson  */
102ca0716f5SRobert Watson static int
103ca0716f5SRobert Watson getstrfromtype_locked(char *name, char **str)
104ca0716f5SRobert Watson {
105ca0716f5SRobert Watson 	char *type, *nl;
106ca0716f5SRobert Watson 	char *tokptr;
107ca0716f5SRobert Watson 	char *last;
108ca0716f5SRobert Watson 
109ca0716f5SRobert Watson 	*str = NULL;
110ca0716f5SRobert Watson 
111ca0716f5SRobert Watson 	if ((fp == NULL) && ((fp = fopen(AUDIT_CONTROL_FILE, "r")) == NULL))
112ca0716f5SRobert Watson 		return (-1); /* Error */
113ca0716f5SRobert Watson 
114ca0716f5SRobert Watson 	while (1) {
115ca0716f5SRobert Watson 		if (fgets(linestr, AU_LINE_MAX, fp) == NULL) {
116ca0716f5SRobert Watson 			if (ferror(fp))
117ca0716f5SRobert Watson 				return (-1);
118ca0716f5SRobert Watson 			return (0);	/* EOF */
119ca0716f5SRobert Watson 		}
120ca0716f5SRobert Watson 
121ca0716f5SRobert Watson 		if (linestr[0] == '#')
122ca0716f5SRobert Watson 			continue;
123ca0716f5SRobert Watson 
124597df30eSRobert Watson 		/* Remove trailing new line character and white space. */
125597df30eSRobert Watson 		nl = strchr(linestr, '\0') - 1;
126597df30eSRobert Watson 		while (nl >= linestr && ('\n' == *nl || ' ' == *nl ||
127597df30eSRobert Watson 			'\t' == *nl)) {
128ca0716f5SRobert Watson 			*nl = '\0';
129597df30eSRobert Watson 			nl--;
130597df30eSRobert Watson 		}
131ca0716f5SRobert Watson 
132ca0716f5SRobert Watson 		tokptr = linestr;
133ca0716f5SRobert Watson 		if ((type = strtok_r(tokptr, delim, &last)) != NULL) {
134ca0716f5SRobert Watson 			if (strcmp(name, type) == 0) {
135ca0716f5SRobert Watson 				/* Found matching name. */
136ca0716f5SRobert Watson 				*str = strtok_r(NULL, delim, &last);
137ca0716f5SRobert Watson 				if (*str == NULL) {
138ca0716f5SRobert Watson 					errno = EINVAL;
139ca0716f5SRobert Watson 					return (-1); /* Parse error in file */
140ca0716f5SRobert Watson 				}
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
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
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
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
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
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
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
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
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 /*
400bb97b418SRobert Watson  * Return the minimum free diskspace value from the audit control file.
401ca0716f5SRobert Watson  */
402ca0716f5SRobert Watson int
403ca0716f5SRobert Watson getacmin(int *min_val)
404ca0716f5SRobert Watson {
405ca0716f5SRobert Watson 	char *min;
406ca0716f5SRobert Watson 
4077a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
408ca0716f5SRobert Watson 	pthread_mutex_lock(&mutex);
4097a0a89d2SRobert Watson #endif
410bb97b418SRobert Watson 	setac_locked();
411ca0716f5SRobert Watson 	if (getstrfromtype_locked(MINFREE_CONTROL_ENTRY, &min) < 0) {
4127a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
413ca0716f5SRobert Watson 		pthread_mutex_unlock(&mutex);
4147a0a89d2SRobert Watson #endif
415ca0716f5SRobert Watson 		return (-2);
416ca0716f5SRobert Watson 	}
417bb97b418SRobert Watson 	if (min == NULL) {
4187a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
419ca0716f5SRobert Watson 		pthread_mutex_unlock(&mutex);
4207a0a89d2SRobert Watson #endif
421ca0716f5SRobert Watson 		return (1);
422bb97b418SRobert Watson 	}
423ca0716f5SRobert Watson 	*min_val = atoi(min);
4247a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
425bb97b418SRobert Watson 	pthread_mutex_unlock(&mutex);
4267a0a89d2SRobert Watson #endif
427ca0716f5SRobert Watson 	return (0);
428ca0716f5SRobert Watson }
429ca0716f5SRobert Watson 
430ca0716f5SRobert Watson /*
4314bd0c025SRobert Watson  * Return the desired trail rotation size from the audit control file.
4324bd0c025SRobert Watson  */
4334bd0c025SRobert Watson int
4344bd0c025SRobert Watson getacfilesz(size_t *filesz_val)
4354bd0c025SRobert Watson {
43606edd2f1SRobert Watson 	char *str;
43706edd2f1SRobert Watson 	size_t val;
43806edd2f1SRobert Watson 	char mult;
43906edd2f1SRobert Watson 	int nparsed;
4404bd0c025SRobert Watson 
4417a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
4424bd0c025SRobert Watson 	pthread_mutex_lock(&mutex);
4437a0a89d2SRobert Watson #endif
4444bd0c025SRobert Watson 	setac_locked();
44506edd2f1SRobert Watson 	if (getstrfromtype_locked(FILESZ_CONTROL_ENTRY, &str) < 0) {
4467a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
4474bd0c025SRobert Watson 		pthread_mutex_unlock(&mutex);
4487a0a89d2SRobert Watson #endif
4494bd0c025SRobert Watson 		return (-2);
4504bd0c025SRobert Watson 	}
45106edd2f1SRobert Watson 	if (str == NULL) {
4527a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
4534bd0c025SRobert Watson 		pthread_mutex_unlock(&mutex);
4547a0a89d2SRobert Watson #endif
4554bd0c025SRobert Watson 		errno = EINVAL;
4564bd0c025SRobert Watson 		return (1);
4574bd0c025SRobert Watson 	}
45806edd2f1SRobert Watson 
45906edd2f1SRobert Watson 	/* Trim off any leading white space. */
46006edd2f1SRobert Watson 	while (*str == ' ' || *str == '\t')
46106edd2f1SRobert Watson 		str++;
46206edd2f1SRobert Watson 
46306edd2f1SRobert Watson 	nparsed = sscanf(str, "%ju%c", (uintmax_t *)&val, &mult);
46406edd2f1SRobert Watson 
46506edd2f1SRobert Watson 	switch (nparsed) {
46606edd2f1SRobert Watson 	case 1:
46706edd2f1SRobert Watson 		/* If no multiplier then assume 'B' (bytes). */
46806edd2f1SRobert Watson 		mult = 'B';
46906edd2f1SRobert Watson 		/* fall through */
47006edd2f1SRobert Watson 	case 2:
47106edd2f1SRobert Watson 		if (au_spacetobytes(filesz_val, val, mult) == 0)
47206edd2f1SRobert Watson 			break;
47306edd2f1SRobert Watson 		/* fall through */
47406edd2f1SRobert Watson 	default:
47506edd2f1SRobert Watson 		errno = EINVAL;
4767a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
4774bd0c025SRobert Watson 		pthread_mutex_unlock(&mutex);
4787a0a89d2SRobert Watson #endif
4794bd0c025SRobert Watson 		return (-1);
4804bd0c025SRobert Watson 	}
48106edd2f1SRobert Watson 
4824bd0c025SRobert Watson 	/*
4834bd0c025SRobert Watson 	 * The file size must either be 0 or >= MIN_AUDIT_FILE_SIZE.  0
4844bd0c025SRobert Watson 	 * indicates no rotation size.
4854bd0c025SRobert Watson 	 */
48606edd2f1SRobert Watson 	if (*filesz_val < 0 || (*filesz_val > 0 &&
48706edd2f1SRobert Watson 		*filesz_val < MIN_AUDIT_FILE_SIZE)) {
4887a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
4894bd0c025SRobert Watson 		pthread_mutex_unlock(&mutex);
4907a0a89d2SRobert Watson #endif
49106edd2f1SRobert Watson 		filesz_val = 0L;
4924bd0c025SRobert Watson 		errno = EINVAL;
4934bd0c025SRobert Watson 		return (-1);
4944bd0c025SRobert Watson 	}
4957a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
4964bd0c025SRobert Watson 	pthread_mutex_unlock(&mutex);
4977a0a89d2SRobert Watson #endif
4984bd0c025SRobert Watson 	return (0);
4994bd0c025SRobert Watson }
5004bd0c025SRobert Watson 
5014bd0c025SRobert Watson /*
502ca0716f5SRobert Watson  * Return the system audit value from the audit contol file.
503ca0716f5SRobert Watson  */
504ca0716f5SRobert Watson int
505ca0716f5SRobert Watson getacflg(char *auditstr, int len)
506ca0716f5SRobert Watson {
507ca0716f5SRobert Watson 	char *str;
508ca0716f5SRobert Watson 
5097a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
510ca0716f5SRobert Watson 	pthread_mutex_lock(&mutex);
5117a0a89d2SRobert Watson #endif
512bb97b418SRobert Watson 	setac_locked();
513ca0716f5SRobert Watson 	if (getstrfromtype_locked(FLAGS_CONTROL_ENTRY, &str) < 0) {
5147a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
515ca0716f5SRobert Watson 		pthread_mutex_unlock(&mutex);
5167a0a89d2SRobert Watson #endif
517ca0716f5SRobert Watson 		return (-2);
518ca0716f5SRobert Watson 	}
519bb97b418SRobert Watson 	if (str == NULL) {
5207a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
521ca0716f5SRobert Watson 		pthread_mutex_unlock(&mutex);
5227a0a89d2SRobert Watson #endif
523ca0716f5SRobert Watson 		return (1);
524bb97b418SRobert Watson 	}
52552267f74SRobert Watson 	if (strlen(str) >= (size_t)len) {
5267a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
527bb97b418SRobert Watson 		pthread_mutex_unlock(&mutex);
5287a0a89d2SRobert Watson #endif
529ca0716f5SRobert Watson 		return (-3);
530bb97b418SRobert Watson 	}
53152267f74SRobert Watson 	strlcpy(auditstr, str, len);
5327a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
533bb97b418SRobert Watson 	pthread_mutex_unlock(&mutex);
5347a0a89d2SRobert Watson #endif
535ca0716f5SRobert Watson 	return (0);
536ca0716f5SRobert Watson }
537ca0716f5SRobert Watson 
538ca0716f5SRobert Watson /*
539ca0716f5SRobert Watson  * Return the non attributable flags from the audit contol file.
540ca0716f5SRobert Watson  */
541ca0716f5SRobert Watson int
542ca0716f5SRobert Watson getacna(char *auditstr, int len)
543ca0716f5SRobert Watson {
544ca0716f5SRobert Watson 	char *str;
545ca0716f5SRobert Watson 
5467a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
547ca0716f5SRobert Watson 	pthread_mutex_lock(&mutex);
5487a0a89d2SRobert Watson #endif
549bb97b418SRobert Watson 	setac_locked();
550ca0716f5SRobert Watson 	if (getstrfromtype_locked(NA_CONTROL_ENTRY, &str) < 0) {
5517a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
552ca0716f5SRobert Watson 		pthread_mutex_unlock(&mutex);
5537a0a89d2SRobert Watson #endif
554ca0716f5SRobert Watson 		return (-2);
555ca0716f5SRobert Watson 	}
556bb97b418SRobert Watson 	if (str == NULL) {
5577a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
558ca0716f5SRobert Watson 		pthread_mutex_unlock(&mutex);
5597a0a89d2SRobert Watson #endif
560ca0716f5SRobert Watson 		return (1);
561bb97b418SRobert Watson 	}
56252267f74SRobert Watson 	if (strlen(str) >= (size_t)len) {
5637a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
564bb97b418SRobert Watson 		pthread_mutex_unlock(&mutex);
5657a0a89d2SRobert Watson #endif
566ca0716f5SRobert Watson 		return (-3);
567bb97b418SRobert Watson 	}
56852267f74SRobert Watson 	strlcpy(auditstr, str, len);
5697a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
57052267f74SRobert Watson 	pthread_mutex_unlock(&mutex);
5717a0a89d2SRobert Watson #endif
572bb97b418SRobert Watson 	return (0);
573bb97b418SRobert Watson }
574ca0716f5SRobert Watson 
575bb97b418SRobert Watson /*
576bb97b418SRobert Watson  * Return the policy field from the audit control file.
577bb97b418SRobert Watson  */
578bb97b418SRobert Watson int
579bb97b418SRobert Watson getacpol(char *auditstr, size_t len)
580bb97b418SRobert Watson {
581bb97b418SRobert Watson 	char *str;
582bb97b418SRobert Watson 
5837a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
584bb97b418SRobert Watson 	pthread_mutex_lock(&mutex);
5857a0a89d2SRobert Watson #endif
586bb97b418SRobert Watson 	setac_locked();
587bb97b418SRobert Watson 	if (getstrfromtype_locked(POLICY_CONTROL_ENTRY, &str) < 0) {
5887a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
589bb97b418SRobert Watson 		pthread_mutex_unlock(&mutex);
5907a0a89d2SRobert Watson #endif
591bb97b418SRobert Watson 		return (-2);
592bb97b418SRobert Watson 	}
593bb97b418SRobert Watson 	if (str == NULL) {
5947a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
595bb97b418SRobert Watson 		pthread_mutex_unlock(&mutex);
5967a0a89d2SRobert Watson #endif
597bb97b418SRobert Watson 		return (-1);
598bb97b418SRobert Watson 	}
599bb97b418SRobert Watson 	if (strlen(str) >= len) {
6007a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
601bb97b418SRobert Watson 		pthread_mutex_unlock(&mutex);
6027a0a89d2SRobert Watson #endif
603bb97b418SRobert Watson 		return (-3);
604bb97b418SRobert Watson 	}
60552267f74SRobert Watson 	strlcpy(auditstr, str, len);
6067a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
60752267f74SRobert Watson 	pthread_mutex_unlock(&mutex);
6087a0a89d2SRobert Watson #endif
60952267f74SRobert Watson 	return (0);
61052267f74SRobert Watson }
61152267f74SRobert Watson 
61252267f74SRobert Watson int
61352267f74SRobert Watson getachost(char *auditstr, size_t len)
61452267f74SRobert Watson {
61552267f74SRobert Watson 	char *str;
61652267f74SRobert Watson 
6177a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
61852267f74SRobert Watson 	pthread_mutex_lock(&mutex);
6197a0a89d2SRobert Watson #endif
62052267f74SRobert Watson 	setac_locked();
62152267f74SRobert Watson 	if (getstrfromtype_locked(AUDIT_HOST_CONTROL_ENTRY, &str) < 0) {
6227a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
62352267f74SRobert Watson 		pthread_mutex_unlock(&mutex);
6247a0a89d2SRobert Watson #endif
62552267f74SRobert Watson 		return (-2);
62652267f74SRobert Watson 	}
62752267f74SRobert Watson 	if (str == NULL) {
6287a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
62952267f74SRobert Watson 		pthread_mutex_unlock(&mutex);
6307a0a89d2SRobert Watson #endif
63152267f74SRobert Watson 		return (1);
63252267f74SRobert Watson 	}
63352267f74SRobert Watson 	if (strlen(str) >= len) {
6347a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
63552267f74SRobert Watson 		pthread_mutex_unlock(&mutex);
6367a0a89d2SRobert Watson #endif
63752267f74SRobert Watson 		return (-3);
63852267f74SRobert Watson 	}
63906edd2f1SRobert Watson 	strlcpy(auditstr, str, len);
64006edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
64106edd2f1SRobert Watson 	pthread_mutex_unlock(&mutex);
64206edd2f1SRobert Watson #endif
64306edd2f1SRobert Watson 	return (0);
64406edd2f1SRobert Watson }
64506edd2f1SRobert Watson 
64606edd2f1SRobert Watson /*
64706edd2f1SRobert Watson  * Set expiration conditions.
64806edd2f1SRobert Watson  */
64906edd2f1SRobert Watson static int
65006edd2f1SRobert Watson setexpirecond(time_t *age, size_t *size, u_long value, char mult)
65106edd2f1SRobert Watson {
65206edd2f1SRobert Watson 
65306edd2f1SRobert Watson 	if (isupper(mult) || ' ' == mult)
65406edd2f1SRobert Watson 		return (au_spacetobytes(size, value, mult));
65506edd2f1SRobert Watson 	else
65606edd2f1SRobert Watson 		return (au_timetosec(age, value, mult));
65706edd2f1SRobert Watson }
65806edd2f1SRobert Watson 
65906edd2f1SRobert Watson /*
66006edd2f1SRobert Watson  * Return the expire-after field from the audit control file.
66106edd2f1SRobert Watson  */
66206edd2f1SRobert Watson int
66306edd2f1SRobert Watson getacexpire(int *andflg, time_t *age, size_t *size)
66406edd2f1SRobert Watson {
66506edd2f1SRobert Watson 	char *str;
66606edd2f1SRobert Watson 	int nparsed;
66706edd2f1SRobert Watson 	u_long val1, val2;
66806edd2f1SRobert Watson 	char mult1, mult2;
66906edd2f1SRobert Watson 	char andor[AU_LINE_MAX];
67006edd2f1SRobert Watson 
67106edd2f1SRobert Watson 	*age = 0L;
67206edd2f1SRobert Watson 	*size = 0LL;
67306edd2f1SRobert Watson 	*andflg = 0;
67406edd2f1SRobert Watson 
67506edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
67606edd2f1SRobert Watson 	pthread_mutex_lock(&mutex);
67706edd2f1SRobert Watson #endif
67806edd2f1SRobert Watson 	setac_locked();
67906edd2f1SRobert Watson 	if (getstrfromtype_locked(EXPIRE_AFTER_CONTROL_ENTRY, &str) < 0) {
68006edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
68106edd2f1SRobert Watson 		pthread_mutex_unlock(&mutex);
68206edd2f1SRobert Watson #endif
68306edd2f1SRobert Watson 		return (-2);
68406edd2f1SRobert Watson 	}
68506edd2f1SRobert Watson 	if (str == NULL) {
68606edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
68706edd2f1SRobert Watson 		pthread_mutex_unlock(&mutex);
68806edd2f1SRobert Watson #endif
68906edd2f1SRobert Watson 		return (1);
69006edd2f1SRobert Watson 	}
69106edd2f1SRobert Watson 
69206edd2f1SRobert Watson 	/* First, trim off any leading white space. */
69306edd2f1SRobert Watson 	while (*str == ' ' || *str == '\t')
69406edd2f1SRobert Watson 		str++;
69506edd2f1SRobert Watson 
69606edd2f1SRobert Watson 	nparsed = sscanf(str, "%lu%c%[ \tadnorADNOR]%lu%c", &val1, &mult1,
69706edd2f1SRobert Watson 	    andor, &val2, &mult2);
69806edd2f1SRobert Watson 
69906edd2f1SRobert Watson 	switch (nparsed) {
70006edd2f1SRobert Watson 	case 1:
70106edd2f1SRobert Watson 		/* If no multiplier then assume 'B' (Bytes). */
70206edd2f1SRobert Watson 		mult1 = 'B';
70306edd2f1SRobert Watson 		/* fall through */
70406edd2f1SRobert Watson 	case 2:
70506edd2f1SRobert Watson 		/* One expiration condition. */
70606edd2f1SRobert Watson 		if (setexpirecond(age, size, val1, mult1) != 0) {
70706edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
70806edd2f1SRobert Watson 			pthread_mutex_unlock(&mutex);
70906edd2f1SRobert Watson #endif
71006edd2f1SRobert Watson 			return (-1);
71106edd2f1SRobert Watson 		}
71206edd2f1SRobert Watson 		break;
71306edd2f1SRobert Watson 
71406edd2f1SRobert Watson 	case 5:
71506edd2f1SRobert Watson 		/* Two expiration conditions. */
71606edd2f1SRobert Watson 		if (setexpirecond(age, size, val1, mult1) != 0 ||
71706edd2f1SRobert Watson 		    setexpirecond(age, size, val2, mult2) != 0) {
71806edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
71906edd2f1SRobert Watson 			pthread_mutex_unlock(&mutex);
72006edd2f1SRobert Watson #endif
72106edd2f1SRobert Watson 			return (-1);
72206edd2f1SRobert Watson 		}
72306edd2f1SRobert Watson 		if (strcasestr(andor, "and") != NULL)
72406edd2f1SRobert Watson 			*andflg = 1;
72506edd2f1SRobert Watson 		else if (strcasestr(andor, "or") != NULL)
72606edd2f1SRobert Watson 			*andflg = 0;
72706edd2f1SRobert Watson 		else {
72806edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
72906edd2f1SRobert Watson 			pthread_mutex_unlock(&mutex);
73006edd2f1SRobert Watson #endif
73106edd2f1SRobert Watson 			return (-1);
73206edd2f1SRobert Watson 		}
73306edd2f1SRobert Watson 		break;
73406edd2f1SRobert Watson 
73506edd2f1SRobert Watson 	default:
73606edd2f1SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
73706edd2f1SRobert Watson 		pthread_mutex_unlock(&mutex);
73806edd2f1SRobert Watson #endif
73906edd2f1SRobert Watson 		return (-1);
74006edd2f1SRobert Watson 	}
74106edd2f1SRobert Watson 
7427a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
743bb97b418SRobert Watson 	pthread_mutex_unlock(&mutex);
7447a0a89d2SRobert Watson #endif
745ca0716f5SRobert Watson 	return (0);
746ca0716f5SRobert Watson }
747