1185573Srwatson/*-
2191273Srwatson * Copyright (c) 2004, 2009 Apple Inc.
3162503Srwatson * Copyright (c) 2006 Robert N. M. Watson
4155131Srwatson * All rights reserved.
5155131Srwatson *
6155131Srwatson * Redistribution and use in source and binary forms, with or without
7155131Srwatson * modification, are permitted provided that the following conditions
8155131Srwatson * are met:
9155131Srwatson * 1.  Redistributions of source code must retain the above copyright
10155131Srwatson *     notice, this list of conditions and the following disclaimer.
11155131Srwatson * 2.  Redistributions in binary form must reproduce the above copyright
12155131Srwatson *     notice, this list of conditions and the following disclaimer in the
13155131Srwatson *     documentation and/or other materials provided with the distribution.
14185573Srwatson * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
15155131Srwatson *     its contributors may be used to endorse or promote products derived
16155131Srwatson *     from this software without specific prior written permission.
17155131Srwatson *
18155131Srwatson * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
19155131Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20155131Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21155131Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
22155131Srwatson * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23155131Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24155131Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25155131Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26155131Srwatson * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27155131Srwatson * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28155131Srwatson * POSSIBILITY OF SUCH DAMAGE.
29155131Srwatson *
30244390Srwatson * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_control.c#41 $
31155131Srwatson */
32155131Srwatson
33185573Srwatson#include <config/config.h>
34185573Srwatson
35155131Srwatson#include <bsm/libbsm.h>
36155131Srwatson
37189279Srwatson#include <ctype.h>
38155131Srwatson#include <errno.h>
39155131Srwatson#include <string.h>
40244390Srwatson#include <strings.h>
41186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
42155131Srwatson#include <pthread.h>
43186647Srwatson#endif
44155131Srwatson#include <stdio.h>
45155131Srwatson#include <stdlib.h>
46155131Srwatson
47162503Srwatson#ifndef HAVE_STRLCAT
48162503Srwatson#include <compat/strlcat.h>
49162503Srwatson#endif
50185573Srwatson#ifndef HAVE_STRLCPY
51185573Srwatson#include <compat/strlcpy.h>
52185573Srwatson#endif
53162503Srwatson
54191273Srwatson#include <sys/stat.h>
55191273Srwatson
56155131Srwatson/*
57155131Srwatson * Parse the contents of the audit_control file to return the audit control
58162503Srwatson * parameters.  These static fields are protected by 'mutex'.
59155131Srwatson */
60155131Srwatsonstatic FILE	*fp = NULL;
61155131Srwatsonstatic char	linestr[AU_LINE_MAX];
62155131Srwatsonstatic char	*delim = ":";
63155131Srwatson
64155131Srwatsonstatic char	inacdir = 0;
65155131Srwatsonstatic char	ptrmoved = 0;
66155131Srwatson
67186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
68155131Srwatsonstatic pthread_mutex_t	mutex = PTHREAD_MUTEX_INITIALIZER;
69186647Srwatson#endif
70155131Srwatson
71155131Srwatson/*
72189279Srwatson * Audit policy string token table for au_poltostr() and au_strtopol().
73189279Srwatson */
74189279Srwatsonstruct audit_polstr {
75244390Srwatson	long		 ap_policy;
76244390Srwatson	const char	*ap_str;
77189279Srwatson};
78189279Srwatson
79189279Srwatsonstatic struct audit_polstr au_polstr[] = {
80189279Srwatson	{ AUDIT_CNT,		"cnt"		},
81189279Srwatson	{ AUDIT_AHLT,		"ahlt"		},
82189279Srwatson	{ AUDIT_ARGV,		"argv"		},
83189279Srwatson	{ AUDIT_ARGE,		"arge"		},
84189279Srwatson	{ AUDIT_SEQ,		"seq"		},
85189279Srwatson	{ AUDIT_WINDATA,	"windata"	},
86189279Srwatson	{ AUDIT_USER,		"user"		},
87189279Srwatson	{ AUDIT_GROUP,		"group"		},
88189279Srwatson	{ AUDIT_TRAIL,		"trail"		},
89189279Srwatson	{ AUDIT_PATH,		"path"		},
90189279Srwatson	{ AUDIT_SCNT,		"scnt"		},
91189279Srwatson	{ AUDIT_PUBLIC,		"public"	},
92189279Srwatson	{ AUDIT_ZONENAME,	"zonename"	},
93189279Srwatson	{ AUDIT_PERZONE,	"perzone"	},
94189279Srwatson	{ -1,			NULL		}
95189279Srwatson};
96189279Srwatson
97189279Srwatson/*
98155131Srwatson * Returns the string value corresponding to the given label from the
99155131Srwatson * configuration file.
100155131Srwatson *
101155131Srwatson * Must be called with mutex held.
102155131Srwatson */
103155131Srwatsonstatic int
104244390Srwatsongetstrfromtype_locked(const char *name, char **str)
105155131Srwatson{
106155131Srwatson	char *type, *nl;
107155131Srwatson	char *tokptr;
108155131Srwatson	char *last;
109155131Srwatson
110155131Srwatson	*str = NULL;
111155131Srwatson
112155131Srwatson	if ((fp == NULL) && ((fp = fopen(AUDIT_CONTROL_FILE, "r")) == NULL))
113155131Srwatson		return (-1); /* Error */
114155131Srwatson
115155131Srwatson	while (1) {
116155131Srwatson		if (fgets(linestr, AU_LINE_MAX, fp) == NULL) {
117155131Srwatson			if (ferror(fp))
118155131Srwatson				return (-1);
119155131Srwatson			return (0);	/* EOF */
120155131Srwatson		}
121155131Srwatson
122155131Srwatson		if (linestr[0] == '#')
123155131Srwatson			continue;
124155131Srwatson
125195740Srwatson		/* Remove trailing new line character and white space. */
126195740Srwatson		nl = strchr(linestr, '\0') - 1;
127195740Srwatson		while (nl >= linestr && ('\n' == *nl || ' ' == *nl ||
128195740Srwatson			'\t' == *nl)) {
129155131Srwatson			*nl = '\0';
130195740Srwatson			nl--;
131195740Srwatson		}
132155131Srwatson
133155131Srwatson		tokptr = linestr;
134155131Srwatson		if ((type = strtok_r(tokptr, delim, &last)) != NULL) {
135155131Srwatson			if (strcmp(name, type) == 0) {
136155131Srwatson				/* Found matching name. */
137155131Srwatson				*str = strtok_r(NULL, delim, &last);
138155131Srwatson				if (*str == NULL) {
139155131Srwatson					errno = EINVAL;
140155131Srwatson					return (-1); /* Parse error in file */
141155131Srwatson				}
142155131Srwatson				return (0); /* Success */
143155131Srwatson			}
144155131Srwatson		}
145155131Srwatson	}
146155131Srwatson}
147155131Srwatson
148155131Srwatson/*
149189279Srwatson * Convert a given time value with a multiplier (seconds, hours, days, years) to
150189279Srwatson * seconds.  Return 0 on success.
151189279Srwatson */
152189279Srwatsonstatic int
153189279Srwatsonau_timetosec(time_t *seconds, u_long value, char mult)
154189279Srwatson{
155189279Srwatson	if (NULL == seconds)
156189279Srwatson		return (-1);
157189279Srwatson
158189279Srwatson	switch(mult) {
159189279Srwatson	case 's':
160189279Srwatson		/* seconds */
161189279Srwatson		*seconds = (time_t)value;
162189279Srwatson		break;
163189279Srwatson
164189279Srwatson	case 'h':
165189279Srwatson		/* hours */
166189279Srwatson		*seconds = (time_t)value * 60 * 60;
167189279Srwatson		break;
168189279Srwatson
169189279Srwatson	case 'd':
170189279Srwatson		/* days */
171189279Srwatson		*seconds = (time_t)value * 60 * 60 * 24;
172189279Srwatson		break;
173189279Srwatson
174189279Srwatson	case 'y':
175189279Srwatson		/* years.  Add a day for each 4th (leap) year. */
176189279Srwatson		*seconds = (time_t)value * 60 * 60 * 24 * 364 +
177189279Srwatson		    ((time_t)value / 4) * 60 * 60 * 24;
178189279Srwatson		break;
179189279Srwatson
180189279Srwatson	default:
181189279Srwatson		return (-1);
182189279Srwatson	}
183189279Srwatson	return (0);
184189279Srwatson}
185189279Srwatson
186189279Srwatson/*
187244390Srwatson * Convert a given disk space value with a multiplier (bytes, kilobytes,
188189279Srwatson * megabytes, gigabytes) to bytes.  Return 0 on success.
189189279Srwatson */
190189279Srwatsonstatic int
191189279Srwatsonau_spacetobytes(size_t *bytes, u_long value, char mult)
192189279Srwatson{
193189279Srwatson	if (NULL == bytes)
194189279Srwatson		return (-1);
195189279Srwatson
196189279Srwatson	switch(mult) {
197189279Srwatson	case 'B':
198189279Srwatson	case ' ':
199189279Srwatson		/* Bytes */
200189279Srwatson		*bytes = (size_t)value;
201189279Srwatson		break;
202189279Srwatson
203189279Srwatson	case 'K':
204189279Srwatson		/* Kilobytes */
205189279Srwatson		*bytes = (size_t)value * 1024;
206189279Srwatson		break;
207189279Srwatson
208189279Srwatson	case 'M':
209189279Srwatson		/* Megabytes */
210189279Srwatson		*bytes = (size_t)value * 1024 * 1024;
211189279Srwatson		break;
212189279Srwatson
213189279Srwatson	case 'G':
214189279Srwatson		/* Gigabytes */
215189279Srwatson		*bytes = (size_t)value * 1024 * 1024 * 1024;
216189279Srwatson		break;
217189279Srwatson
218189279Srwatson	default:
219189279Srwatson		return (-1);
220189279Srwatson	}
221189279Srwatson	return (0);
222189279Srwatson}
223189279Srwatson
224189279Srwatson/*
225162503Srwatson * Convert a policy to a string.  Return -1 on failure, or >= 0 representing
226162503Srwatson * the actual size of the string placed in the buffer (excluding terminating
227162503Srwatson * nul).
228162503Srwatson */
229162503Srwatsonssize_t
230191273Srwatsonau_poltostr(int policy, size_t maxsize, char *buf)
231162503Srwatson{
232189279Srwatson	int first = 1;
233189279Srwatson	int i = 0;
234162503Srwatson
235162503Srwatson	if (maxsize < 1)
236162503Srwatson		return (-1);
237162503Srwatson	buf[0] = '\0';
238162503Srwatson
239189279Srwatson	do {
240189279Srwatson		if (policy & au_polstr[i].ap_policy) {
241189279Srwatson			if (!first && strlcat(buf, ",", maxsize) >= maxsize)
242162503Srwatson				return (-1);
243189279Srwatson			if (strlcat(buf, au_polstr[i].ap_str, maxsize) >=
244189279Srwatson			    maxsize)
245162503Srwatson				return (-1);
246189279Srwatson			first = 0;
247162503Srwatson		}
248189279Srwatson	} while (NULL != au_polstr[++i].ap_str);
249189279Srwatson
250162503Srwatson	return (strlen(buf));
251162503Srwatson}
252162503Srwatson
253162503Srwatson/*
254162503Srwatson * Convert a string to a policy.  Return -1 on failure (with errno EINVAL,
255162503Srwatson * ENOMEM) or 0 on success.
256162503Srwatson */
257162503Srwatsonint
258191273Srwatsonau_strtopol(const char *polstr, int *policy)
259162503Srwatson{
260162503Srwatson	char *bufp, *string;
261162503Srwatson	char *buffer;
262189279Srwatson	int i, matched;
263162503Srwatson
264162503Srwatson	*policy = 0;
265162503Srwatson	buffer = strdup(polstr);
266162503Srwatson	if (buffer == NULL)
267162503Srwatson		return (-1);
268162503Srwatson
269162503Srwatson	bufp = buffer;
270162503Srwatson	while ((string = strsep(&bufp, ",")) != NULL) {
271189279Srwatson		matched = i = 0;
272189279Srwatson
273189279Srwatson		do {
274189279Srwatson			if (strcmp(string, au_polstr[i].ap_str) == 0) {
275189279Srwatson				*policy |= au_polstr[i].ap_policy;
276189279Srwatson				matched = 1;
277189279Srwatson				break;
278189279Srwatson			}
279189279Srwatson		} while (NULL != au_polstr[++i].ap_str);
280189279Srwatson
281189279Srwatson		if (!matched) {
282162503Srwatson			free(buffer);
283162503Srwatson			errno = EINVAL;
284162503Srwatson			return (-1);
285162503Srwatson		}
286162503Srwatson	}
287162503Srwatson	free(buffer);
288162503Srwatson	return (0);
289162503Srwatson}
290162503Srwatson
291162503Srwatson/*
292155131Srwatson * Rewind the file pointer to beginning.
293155131Srwatson */
294162503Srwatsonstatic void
295162503Srwatsonsetac_locked(void)
296162503Srwatson{
297191273Srwatson	static time_t lastctime = 0;
298191273Srwatson	struct stat sbuf;
299162503Srwatson
300162503Srwatson	ptrmoved = 1;
301191273Srwatson	if (fp != NULL) {
302191273Srwatson		/*
303191273Srwatson		 * Check to see if the file on disk has changed.  If so,
304191273Srwatson		 * force a re-read of the file by closing it.
305191273Srwatson		 */
306191273Srwatson		if (fstat(fileno(fp), &sbuf) < 0)
307191273Srwatson			goto closefp;
308191273Srwatson		if (lastctime != sbuf.st_ctime) {
309191273Srwatson			lastctime = sbuf.st_ctime;
310191273Srwatsonclosefp:
311191273Srwatson			fclose(fp);
312191273Srwatson			fp = NULL;
313191273Srwatson			return;
314191273Srwatson		}
315191273Srwatson
316162503Srwatson		fseek(fp, 0, SEEK_SET);
317191273Srwatson	}
318162503Srwatson}
319162503Srwatson
320155131Srwatsonvoid
321155131Srwatsonsetac(void)
322155131Srwatson{
323155131Srwatson
324186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
325155131Srwatson	pthread_mutex_lock(&mutex);
326186647Srwatson#endif
327162503Srwatson	setac_locked();
328186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
329155131Srwatson	pthread_mutex_unlock(&mutex);
330186647Srwatson#endif
331155131Srwatson}
332155131Srwatson
333155131Srwatson/*
334162503Srwatson * Close the audit_control file.
335155131Srwatson */
336155131Srwatsonvoid
337155131Srwatsonendac(void)
338155131Srwatson{
339155131Srwatson
340186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
341155131Srwatson	pthread_mutex_lock(&mutex);
342186647Srwatson#endif
343155131Srwatson	ptrmoved = 1;
344155131Srwatson	if (fp != NULL) {
345155131Srwatson		fclose(fp);
346155131Srwatson		fp = NULL;
347155131Srwatson	}
348186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
349155131Srwatson	pthread_mutex_unlock(&mutex);
350186647Srwatson#endif
351155131Srwatson}
352155131Srwatson
353155131Srwatson/*
354155131Srwatson * Return audit directory information from the audit control file.
355155131Srwatson */
356155131Srwatsonint
357155131Srwatsongetacdir(char *name, int len)
358155131Srwatson{
359155131Srwatson	char *dir;
360155131Srwatson	int ret = 0;
361155131Srwatson
362155131Srwatson	/*
363162503Srwatson	 * Check if another function was called between successive calls to
364162503Srwatson	 * getacdir.
365155131Srwatson	 */
366186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
367162503Srwatson	pthread_mutex_lock(&mutex);
368186647Srwatson#endif
369155131Srwatson	if (inacdir && ptrmoved) {
370155131Srwatson		ptrmoved = 0;
371155131Srwatson		if (fp != NULL)
372155131Srwatson			fseek(fp, 0, SEEK_SET);
373155131Srwatson		ret = 2;
374155131Srwatson	}
375155131Srwatson	if (getstrfromtype_locked(DIR_CONTROL_ENTRY, &dir) < 0) {
376186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
377155131Srwatson		pthread_mutex_unlock(&mutex);
378186647Srwatson#endif
379155131Srwatson		return (-2);
380155131Srwatson	}
381162503Srwatson	if (dir == NULL) {
382186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
383162503Srwatson		pthread_mutex_unlock(&mutex);
384186647Srwatson#endif
385155131Srwatson		return (-1);
386162503Srwatson	}
387185573Srwatson	if (strlen(dir) >= (size_t)len) {
388186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
389162503Srwatson		pthread_mutex_unlock(&mutex);
390186647Srwatson#endif
391155131Srwatson		return (-3);
392162503Srwatson	}
393185573Srwatson	strlcpy(name, dir, len);
394186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
395162503Srwatson	pthread_mutex_unlock(&mutex);
396186647Srwatson#endif
397155131Srwatson	return (ret);
398155131Srwatson}
399155131Srwatson
400155131Srwatson/*
401244390Srwatson * Return 1 if dist value is set to 'yes' or 'on'.
402244390Srwatson * Return 0 if dist value is set to something else.
403244390Srwatson * Return negative value on error.
404244390Srwatson */
405244390Srwatsonint
406244390Srwatsongetacdist(void)
407244390Srwatson{
408244390Srwatson	char *str;
409244390Srwatson	int ret;
410244390Srwatson
411244390Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
412244390Srwatson	pthread_mutex_lock(&mutex);
413244390Srwatson#endif
414244390Srwatson	setac_locked();
415244390Srwatson	if (getstrfromtype_locked(DIST_CONTROL_ENTRY, &str) < 0) {
416244390Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
417244390Srwatson		pthread_mutex_unlock(&mutex);
418244390Srwatson#endif
419244390Srwatson		return (-2);
420244390Srwatson	}
421244390Srwatson	if (str == NULL) {
422244390Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
423244390Srwatson		pthread_mutex_unlock(&mutex);
424244390Srwatson#endif
425244390Srwatson		return (0);
426244390Srwatson	}
427244390Srwatson	if (strcasecmp(str, "on") == 0 || strcasecmp(str, "yes") == 0)
428244390Srwatson		ret = 1;
429244390Srwatson	else
430244390Srwatson		ret = 0;
431244390Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
432244390Srwatson	pthread_mutex_unlock(&mutex);
433244390Srwatson#endif
434244390Srwatson	return (ret);
435244390Srwatson}
436244390Srwatson
437244390Srwatson/*
438162503Srwatson * Return the minimum free diskspace value from the audit control file.
439155131Srwatson */
440155131Srwatsonint
441155131Srwatsongetacmin(int *min_val)
442155131Srwatson{
443155131Srwatson	char *min;
444155131Srwatson
445186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
446155131Srwatson	pthread_mutex_lock(&mutex);
447186647Srwatson#endif
448162503Srwatson	setac_locked();
449155131Srwatson	if (getstrfromtype_locked(MINFREE_CONTROL_ENTRY, &min) < 0) {
450186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
451155131Srwatson		pthread_mutex_unlock(&mutex);
452186647Srwatson#endif
453155131Srwatson		return (-2);
454155131Srwatson	}
455162503Srwatson	if (min == NULL) {
456186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
457162503Srwatson		pthread_mutex_unlock(&mutex);
458186647Srwatson#endif
459244390Srwatson		return (-1);
460162503Srwatson	}
461155131Srwatson	*min_val = atoi(min);
462186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
463162503Srwatson	pthread_mutex_unlock(&mutex);
464186647Srwatson#endif
465155131Srwatson	return (0);
466155131Srwatson}
467155131Srwatson
468155131Srwatson/*
469162621Srwatson * Return the desired trail rotation size from the audit control file.
470162621Srwatson */
471162621Srwatsonint
472162621Srwatsongetacfilesz(size_t *filesz_val)
473162621Srwatson{
474189279Srwatson	char *str;
475189279Srwatson	size_t val;
476189279Srwatson	char mult;
477189279Srwatson	int nparsed;
478162621Srwatson
479186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
480162621Srwatson	pthread_mutex_lock(&mutex);
481186647Srwatson#endif
482162621Srwatson	setac_locked();
483189279Srwatson	if (getstrfromtype_locked(FILESZ_CONTROL_ENTRY, &str) < 0) {
484186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
485162621Srwatson		pthread_mutex_unlock(&mutex);
486186647Srwatson#endif
487162621Srwatson		return (-2);
488162621Srwatson	}
489189279Srwatson	if (str == NULL) {
490186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
491162621Srwatson		pthread_mutex_unlock(&mutex);
492186647Srwatson#endif
493162621Srwatson		errno = EINVAL;
494244390Srwatson		return (-1);
495162621Srwatson	}
496189279Srwatson
497189279Srwatson	/* Trim off any leading white space. */
498189279Srwatson	while (*str == ' ' || *str == '\t')
499189279Srwatson		str++;
500189279Srwatson
501189279Srwatson	nparsed = sscanf(str, "%ju%c", (uintmax_t *)&val, &mult);
502189279Srwatson
503189279Srwatson	switch (nparsed) {
504189279Srwatson	case 1:
505189279Srwatson		/* If no multiplier then assume 'B' (bytes). */
506189279Srwatson		mult = 'B';
507189279Srwatson		/* fall through */
508189279Srwatson	case 2:
509189279Srwatson		if (au_spacetobytes(filesz_val, val, mult) == 0)
510189279Srwatson			break;
511189279Srwatson		/* fall through */
512189279Srwatson	default:
513189279Srwatson		errno = EINVAL;
514186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
515162621Srwatson		pthread_mutex_unlock(&mutex);
516186647Srwatson#endif
517162621Srwatson		return (-1);
518162621Srwatson	}
519189279Srwatson
520162621Srwatson	/*
521162621Srwatson	 * The file size must either be 0 or >= MIN_AUDIT_FILE_SIZE.  0
522162621Srwatson	 * indicates no rotation size.
523162621Srwatson	 */
524189279Srwatson	if (*filesz_val < 0 || (*filesz_val > 0 &&
525189279Srwatson		*filesz_val < MIN_AUDIT_FILE_SIZE)) {
526186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
527162621Srwatson		pthread_mutex_unlock(&mutex);
528186647Srwatson#endif
529189279Srwatson		filesz_val = 0L;
530162621Srwatson		errno = EINVAL;
531162621Srwatson		return (-1);
532162621Srwatson	}
533186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
534162621Srwatson	pthread_mutex_unlock(&mutex);
535186647Srwatson#endif
536162621Srwatson	return (0);
537162621Srwatson}
538162621Srwatson
539244390Srwatsonstatic int
540244390Srwatsongetaccommon(const char *name, char *auditstr, int len)
541155131Srwatson{
542155131Srwatson	char *str;
543155131Srwatson
544186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
545155131Srwatson	pthread_mutex_lock(&mutex);
546186647Srwatson#endif
547162503Srwatson	setac_locked();
548244390Srwatson	if (getstrfromtype_locked(name, &str) < 0) {
549186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
550155131Srwatson		pthread_mutex_unlock(&mutex);
551186647Srwatson#endif
552155131Srwatson		return (-2);
553155131Srwatson	}
554162503Srwatson	if (str == NULL) {
555186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
556162503Srwatson		pthread_mutex_unlock(&mutex);
557186647Srwatson#endif
558244390Srwatson		return (-1);
559162503Srwatson	}
560185573Srwatson	if (strlen(str) >= (size_t)len) {
561186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
562162503Srwatson		pthread_mutex_unlock(&mutex);
563186647Srwatson#endif
564155131Srwatson		return (-3);
565162503Srwatson	}
566185573Srwatson	strlcpy(auditstr, str, len);
567186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
568162503Srwatson	pthread_mutex_unlock(&mutex);
569186647Srwatson#endif
570155131Srwatson	return (0);
571155131Srwatson}
572155131Srwatson
573155131Srwatson/*
574244390Srwatson * Return the system audit value from the audit contol file.
575244390Srwatson */
576244390Srwatsonint
577244390Srwatsongetacflg(char *auditstr, int len)
578244390Srwatson{
579244390Srwatson
580244390Srwatson	return (getaccommon(FLAGS_CONTROL_ENTRY, auditstr, len));
581244390Srwatson}
582244390Srwatson
583244390Srwatson/*
584155131Srwatson * Return the non attributable flags from the audit contol file.
585155131Srwatson */
586155131Srwatsonint
587155131Srwatsongetacna(char *auditstr, int len)
588155131Srwatson{
589155131Srwatson
590244390Srwatson	return (getaccommon(NA_CONTROL_ENTRY, auditstr, len));
591162503Srwatson}
592155131Srwatson
593162503Srwatson/*
594162503Srwatson * Return the policy field from the audit control file.
595162503Srwatson */
596162503Srwatsonint
597162503Srwatsongetacpol(char *auditstr, size_t len)
598162503Srwatson{
599162503Srwatson
600244390Srwatson	return (getaccommon(POLICY_CONTROL_ENTRY, auditstr, len));
601185573Srwatson}
602185573Srwatson
603185573Srwatsonint
604185573Srwatsongetachost(char *auditstr, size_t len)
605185573Srwatson{
606185573Srwatson
607244390Srwatson	return (getaccommon(HOST_CONTROL_ENTRY, auditstr, len));
608155131Srwatson}
609189279Srwatson
610189279Srwatson/*
611189279Srwatson * Set expiration conditions.
612189279Srwatson */
613189279Srwatsonstatic int
614189279Srwatsonsetexpirecond(time_t *age, size_t *size, u_long value, char mult)
615189279Srwatson{
616189279Srwatson
617189279Srwatson	if (isupper(mult) || ' ' == mult)
618189279Srwatson		return (au_spacetobytes(size, value, mult));
619189279Srwatson	else
620189279Srwatson		return (au_timetosec(age, value, mult));
621189279Srwatson}
622189279Srwatson
623189279Srwatson/*
624189279Srwatson * Return the expire-after field from the audit control file.
625189279Srwatson */
626189279Srwatsonint
627189279Srwatsongetacexpire(int *andflg, time_t *age, size_t *size)
628189279Srwatson{
629189279Srwatson	char *str;
630189279Srwatson	int nparsed;
631189279Srwatson	u_long val1, val2;
632189279Srwatson	char mult1, mult2;
633189279Srwatson	char andor[AU_LINE_MAX];
634189279Srwatson
635189279Srwatson	*age = 0L;
636189279Srwatson	*size = 0LL;
637189279Srwatson	*andflg = 0;
638189279Srwatson
639189279Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
640189279Srwatson	pthread_mutex_lock(&mutex);
641189279Srwatson#endif
642189279Srwatson	setac_locked();
643189279Srwatson	if (getstrfromtype_locked(EXPIRE_AFTER_CONTROL_ENTRY, &str) < 0) {
644189279Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
645189279Srwatson		pthread_mutex_unlock(&mutex);
646189279Srwatson#endif
647189279Srwatson		return (-2);
648189279Srwatson	}
649189279Srwatson	if (str == NULL) {
650189279Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
651189279Srwatson		pthread_mutex_unlock(&mutex);
652189279Srwatson#endif
653244390Srwatson		return (-1);
654189279Srwatson	}
655189279Srwatson
656189279Srwatson	/* First, trim off any leading white space. */
657189279Srwatson	while (*str == ' ' || *str == '\t')
658244390Srwatson		str++;
659189279Srwatson
660189279Srwatson	nparsed = sscanf(str, "%lu%c%[ \tadnorADNOR]%lu%c", &val1, &mult1,
661189279Srwatson	    andor, &val2, &mult2);
662189279Srwatson
663189279Srwatson	switch (nparsed) {
664189279Srwatson	case 1:
665189279Srwatson		/* If no multiplier then assume 'B' (Bytes). */
666189279Srwatson		mult1 = 'B';
667189279Srwatson		/* fall through */
668189279Srwatson	case 2:
669189279Srwatson		/* One expiration condition. */
670189279Srwatson		if (setexpirecond(age, size, val1, mult1) != 0) {
671189279Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
672189279Srwatson			pthread_mutex_unlock(&mutex);
673189279Srwatson#endif
674189279Srwatson			return (-1);
675189279Srwatson		}
676189279Srwatson		break;
677189279Srwatson
678189279Srwatson	case 5:
679189279Srwatson		/* Two expiration conditions. */
680244390Srwatson		if (setexpirecond(age, size, val1, mult1) != 0 ||
681189279Srwatson		    setexpirecond(age, size, val2, mult2) != 0) {
682189279Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
683189279Srwatson			pthread_mutex_unlock(&mutex);
684189279Srwatson#endif
685189279Srwatson			return (-1);
686189279Srwatson		}
687189279Srwatson		if (strcasestr(andor, "and") != NULL)
688189279Srwatson			*andflg = 1;
689189279Srwatson		else if (strcasestr(andor, "or") != NULL)
690189279Srwatson			*andflg = 0;
691189279Srwatson		else {
692189279Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
693189279Srwatson			pthread_mutex_unlock(&mutex);
694189279Srwatson#endif
695189279Srwatson			return (-1);
696189279Srwatson		}
697189279Srwatson		break;
698189279Srwatson
699189279Srwatson	default:
700189279Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
701189279Srwatson		pthread_mutex_unlock(&mutex);
702189279Srwatson#endif
703189279Srwatson		return (-1);
704189279Srwatson	}
705189279Srwatson
706189279Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
707189279Srwatson	pthread_mutex_unlock(&mutex);
708189279Srwatson#endif
709189279Srwatson	return (0);
710189279Srwatson}
711