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 */
30155131Srwatson
31185573Srwatson#include <config/config.h>
32185573Srwatson
33155131Srwatson#include <bsm/libbsm.h>
34155131Srwatson
35189279Srwatson#include <ctype.h>
36155131Srwatson#include <errno.h>
37155131Srwatson#include <string.h>
38243750Srwatson#include <strings.h>
39186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
40155131Srwatson#include <pthread.h>
41186647Srwatson#endif
42155131Srwatson#include <stdio.h>
43155131Srwatson#include <stdlib.h>
44155131Srwatson
45162503Srwatson#ifndef HAVE_STRLCAT
46162503Srwatson#include <compat/strlcat.h>
47162503Srwatson#endif
48185573Srwatson#ifndef HAVE_STRLCPY
49185573Srwatson#include <compat/strlcpy.h>
50185573Srwatson#endif
51162503Srwatson
52191273Srwatson#include <sys/stat.h>
53191273Srwatson
54155131Srwatson/*
55155131Srwatson * Parse the contents of the audit_control file to return the audit control
56162503Srwatson * parameters.  These static fields are protected by 'mutex'.
57155131Srwatson */
58155131Srwatsonstatic FILE	*fp = NULL;
59155131Srwatsonstatic char	linestr[AU_LINE_MAX];
60155131Srwatsonstatic char	*delim = ":";
61155131Srwatson
62155131Srwatsonstatic char	inacdir = 0;
63155131Srwatsonstatic char	ptrmoved = 0;
64155131Srwatson
65186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
66155131Srwatsonstatic pthread_mutex_t	mutex = PTHREAD_MUTEX_INITIALIZER;
67186647Srwatson#endif
68155131Srwatson
69155131Srwatson/*
70189279Srwatson * Audit policy string token table for au_poltostr() and au_strtopol().
71189279Srwatson */
72189279Srwatsonstruct audit_polstr {
73243750Srwatson	long		 ap_policy;
74243750Srwatson	const char	*ap_str;
75189279Srwatson};
76189279Srwatson
77189279Srwatsonstatic struct audit_polstr au_polstr[] = {
78189279Srwatson	{ AUDIT_CNT,		"cnt"		},
79189279Srwatson	{ AUDIT_AHLT,		"ahlt"		},
80189279Srwatson	{ AUDIT_ARGV,		"argv"		},
81189279Srwatson	{ AUDIT_ARGE,		"arge"		},
82189279Srwatson	{ AUDIT_SEQ,		"seq"		},
83189279Srwatson	{ AUDIT_WINDATA,	"windata"	},
84189279Srwatson	{ AUDIT_USER,		"user"		},
85189279Srwatson	{ AUDIT_GROUP,		"group"		},
86189279Srwatson	{ AUDIT_TRAIL,		"trail"		},
87189279Srwatson	{ AUDIT_PATH,		"path"		},
88189279Srwatson	{ AUDIT_SCNT,		"scnt"		},
89189279Srwatson	{ AUDIT_PUBLIC,		"public"	},
90189279Srwatson	{ AUDIT_ZONENAME,	"zonename"	},
91189279Srwatson	{ AUDIT_PERZONE,	"perzone"	},
92189279Srwatson	{ -1,			NULL		}
93189279Srwatson};
94189279Srwatson
95189279Srwatson/*
96155131Srwatson * Returns the string value corresponding to the given label from the
97155131Srwatson * configuration file.
98155131Srwatson *
99155131Srwatson * Must be called with mutex held.
100155131Srwatson */
101155131Srwatsonstatic int
102243750Srwatsongetstrfromtype_locked(const char *name, char **str)
103155131Srwatson{
104155131Srwatson	char *type, *nl;
105155131Srwatson	char *tokptr;
106155131Srwatson	char *last;
107155131Srwatson
108155131Srwatson	*str = NULL;
109155131Srwatson
110155131Srwatson	if ((fp == NULL) && ((fp = fopen(AUDIT_CONTROL_FILE, "r")) == NULL))
111155131Srwatson		return (-1); /* Error */
112155131Srwatson
113155131Srwatson	while (1) {
114155131Srwatson		if (fgets(linestr, AU_LINE_MAX, fp) == NULL) {
115155131Srwatson			if (ferror(fp))
116155131Srwatson				return (-1);
117155131Srwatson			return (0);	/* EOF */
118155131Srwatson		}
119155131Srwatson
120155131Srwatson		if (linestr[0] == '#')
121155131Srwatson			continue;
122155131Srwatson
123195740Srwatson		/* Remove trailing new line character and white space. */
124195740Srwatson		nl = strchr(linestr, '\0') - 1;
125195740Srwatson		while (nl >= linestr && ('\n' == *nl || ' ' == *nl ||
126195740Srwatson			'\t' == *nl)) {
127155131Srwatson			*nl = '\0';
128195740Srwatson			nl--;
129195740Srwatson		}
130155131Srwatson
131155131Srwatson		tokptr = linestr;
132155131Srwatson		if ((type = strtok_r(tokptr, delim, &last)) != NULL) {
133155131Srwatson			if (strcmp(name, type) == 0) {
134155131Srwatson				/* Found matching name. */
135155131Srwatson				*str = strtok_r(NULL, delim, &last);
136155131Srwatson				if (*str == NULL) {
137155131Srwatson					errno = EINVAL;
138155131Srwatson					return (-1); /* Parse error in file */
139155131Srwatson				}
140155131Srwatson				return (0); /* Success */
141155131Srwatson			}
142155131Srwatson		}
143155131Srwatson	}
144155131Srwatson}
145155131Srwatson
146155131Srwatson/*
147189279Srwatson * Convert a given time value with a multiplier (seconds, hours, days, years) to
148189279Srwatson * seconds.  Return 0 on success.
149189279Srwatson */
150189279Srwatsonstatic int
151189279Srwatsonau_timetosec(time_t *seconds, u_long value, char mult)
152189279Srwatson{
153189279Srwatson	if (NULL == seconds)
154189279Srwatson		return (-1);
155189279Srwatson
156189279Srwatson	switch(mult) {
157189279Srwatson	case 's':
158189279Srwatson		/* seconds */
159189279Srwatson		*seconds = (time_t)value;
160189279Srwatson		break;
161189279Srwatson
162189279Srwatson	case 'h':
163189279Srwatson		/* hours */
164189279Srwatson		*seconds = (time_t)value * 60 * 60;
165189279Srwatson		break;
166189279Srwatson
167189279Srwatson	case 'd':
168189279Srwatson		/* days */
169189279Srwatson		*seconds = (time_t)value * 60 * 60 * 24;
170189279Srwatson		break;
171189279Srwatson
172189279Srwatson	case 'y':
173189279Srwatson		/* years.  Add a day for each 4th (leap) year. */
174189279Srwatson		*seconds = (time_t)value * 60 * 60 * 24 * 364 +
175189279Srwatson		    ((time_t)value / 4) * 60 * 60 * 24;
176189279Srwatson		break;
177189279Srwatson
178189279Srwatson	default:
179189279Srwatson		return (-1);
180189279Srwatson	}
181189279Srwatson	return (0);
182189279Srwatson}
183189279Srwatson
184189279Srwatson/*
185243750Srwatson * Convert a given disk space value with a multiplier (bytes, kilobytes,
186189279Srwatson * megabytes, gigabytes) to bytes.  Return 0 on success.
187189279Srwatson */
188189279Srwatsonstatic int
189189279Srwatsonau_spacetobytes(size_t *bytes, u_long value, char mult)
190189279Srwatson{
191189279Srwatson	if (NULL == bytes)
192189279Srwatson		return (-1);
193189279Srwatson
194189279Srwatson	switch(mult) {
195189279Srwatson	case 'B':
196189279Srwatson	case ' ':
197189279Srwatson		/* Bytes */
198189279Srwatson		*bytes = (size_t)value;
199189279Srwatson		break;
200189279Srwatson
201189279Srwatson	case 'K':
202189279Srwatson		/* Kilobytes */
203189279Srwatson		*bytes = (size_t)value * 1024;
204189279Srwatson		break;
205189279Srwatson
206189279Srwatson	case 'M':
207189279Srwatson		/* Megabytes */
208189279Srwatson		*bytes = (size_t)value * 1024 * 1024;
209189279Srwatson		break;
210189279Srwatson
211189279Srwatson	case 'G':
212189279Srwatson		/* Gigabytes */
213189279Srwatson		*bytes = (size_t)value * 1024 * 1024 * 1024;
214189279Srwatson		break;
215189279Srwatson
216189279Srwatson	default:
217189279Srwatson		return (-1);
218189279Srwatson	}
219189279Srwatson	return (0);
220189279Srwatson}
221189279Srwatson
222189279Srwatson/*
223162503Srwatson * Convert a policy to a string.  Return -1 on failure, or >= 0 representing
224162503Srwatson * the actual size of the string placed in the buffer (excluding terminating
225162503Srwatson * nul).
226162503Srwatson */
227162503Srwatsonssize_t
228191273Srwatsonau_poltostr(int policy, size_t maxsize, char *buf)
229162503Srwatson{
230189279Srwatson	int first = 1;
231189279Srwatson	int i = 0;
232162503Srwatson
233162503Srwatson	if (maxsize < 1)
234162503Srwatson		return (-1);
235162503Srwatson	buf[0] = '\0';
236162503Srwatson
237189279Srwatson	do {
238189279Srwatson		if (policy & au_polstr[i].ap_policy) {
239189279Srwatson			if (!first && strlcat(buf, ",", maxsize) >= maxsize)
240162503Srwatson				return (-1);
241189279Srwatson			if (strlcat(buf, au_polstr[i].ap_str, maxsize) >=
242189279Srwatson			    maxsize)
243162503Srwatson				return (-1);
244189279Srwatson			first = 0;
245162503Srwatson		}
246189279Srwatson	} while (NULL != au_polstr[++i].ap_str);
247189279Srwatson
248162503Srwatson	return (strlen(buf));
249162503Srwatson}
250162503Srwatson
251162503Srwatson/*
252162503Srwatson * Convert a string to a policy.  Return -1 on failure (with errno EINVAL,
253162503Srwatson * ENOMEM) or 0 on success.
254162503Srwatson */
255162503Srwatsonint
256191273Srwatsonau_strtopol(const char *polstr, int *policy)
257162503Srwatson{
258162503Srwatson	char *bufp, *string;
259162503Srwatson	char *buffer;
260189279Srwatson	int i, matched;
261162503Srwatson
262162503Srwatson	*policy = 0;
263162503Srwatson	buffer = strdup(polstr);
264162503Srwatson	if (buffer == NULL)
265162503Srwatson		return (-1);
266162503Srwatson
267162503Srwatson	bufp = buffer;
268162503Srwatson	while ((string = strsep(&bufp, ",")) != NULL) {
269189279Srwatson		matched = i = 0;
270189279Srwatson
271189279Srwatson		do {
272189279Srwatson			if (strcmp(string, au_polstr[i].ap_str) == 0) {
273189279Srwatson				*policy |= au_polstr[i].ap_policy;
274189279Srwatson				matched = 1;
275189279Srwatson				break;
276189279Srwatson			}
277189279Srwatson		} while (NULL != au_polstr[++i].ap_str);
278189279Srwatson
279189279Srwatson		if (!matched) {
280162503Srwatson			free(buffer);
281162503Srwatson			errno = EINVAL;
282162503Srwatson			return (-1);
283162503Srwatson		}
284162503Srwatson	}
285162503Srwatson	free(buffer);
286162503Srwatson	return (0);
287162503Srwatson}
288162503Srwatson
289162503Srwatson/*
290155131Srwatson * Rewind the file pointer to beginning.
291155131Srwatson */
292162503Srwatsonstatic void
293162503Srwatsonsetac_locked(void)
294162503Srwatson{
295191273Srwatson	static time_t lastctime = 0;
296191273Srwatson	struct stat sbuf;
297162503Srwatson
298162503Srwatson	ptrmoved = 1;
299191273Srwatson	if (fp != NULL) {
300191273Srwatson		/*
301191273Srwatson		 * Check to see if the file on disk has changed.  If so,
302191273Srwatson		 * force a re-read of the file by closing it.
303191273Srwatson		 */
304191273Srwatson		if (fstat(fileno(fp), &sbuf) < 0)
305191273Srwatson			goto closefp;
306191273Srwatson		if (lastctime != sbuf.st_ctime) {
307191273Srwatson			lastctime = sbuf.st_ctime;
308191273Srwatsonclosefp:
309191273Srwatson			fclose(fp);
310191273Srwatson			fp = NULL;
311191273Srwatson			return;
312191273Srwatson		}
313191273Srwatson
314162503Srwatson		fseek(fp, 0, SEEK_SET);
315191273Srwatson	}
316162503Srwatson}
317162503Srwatson
318155131Srwatsonvoid
319155131Srwatsonsetac(void)
320155131Srwatson{
321155131Srwatson
322186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
323155131Srwatson	pthread_mutex_lock(&mutex);
324186647Srwatson#endif
325162503Srwatson	setac_locked();
326186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
327155131Srwatson	pthread_mutex_unlock(&mutex);
328186647Srwatson#endif
329155131Srwatson}
330155131Srwatson
331155131Srwatson/*
332162503Srwatson * Close the audit_control file.
333155131Srwatson */
334155131Srwatsonvoid
335155131Srwatsonendac(void)
336155131Srwatson{
337155131Srwatson
338186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
339155131Srwatson	pthread_mutex_lock(&mutex);
340186647Srwatson#endif
341155131Srwatson	ptrmoved = 1;
342155131Srwatson	if (fp != NULL) {
343155131Srwatson		fclose(fp);
344155131Srwatson		fp = NULL;
345155131Srwatson	}
346186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
347155131Srwatson	pthread_mutex_unlock(&mutex);
348186647Srwatson#endif
349155131Srwatson}
350155131Srwatson
351155131Srwatson/*
352155131Srwatson * Return audit directory information from the audit control file.
353155131Srwatson */
354155131Srwatsonint
355155131Srwatsongetacdir(char *name, int len)
356155131Srwatson{
357155131Srwatson	char *dir;
358155131Srwatson	int ret = 0;
359155131Srwatson
360155131Srwatson	/*
361162503Srwatson	 * Check if another function was called between successive calls to
362162503Srwatson	 * getacdir.
363155131Srwatson	 */
364186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
365162503Srwatson	pthread_mutex_lock(&mutex);
366186647Srwatson#endif
367155131Srwatson	if (inacdir && ptrmoved) {
368155131Srwatson		ptrmoved = 0;
369155131Srwatson		if (fp != NULL)
370155131Srwatson			fseek(fp, 0, SEEK_SET);
371155131Srwatson		ret = 2;
372155131Srwatson	}
373155131Srwatson	if (getstrfromtype_locked(DIR_CONTROL_ENTRY, &dir) < 0) {
374186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
375155131Srwatson		pthread_mutex_unlock(&mutex);
376186647Srwatson#endif
377155131Srwatson		return (-2);
378155131Srwatson	}
379162503Srwatson	if (dir == NULL) {
380186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
381162503Srwatson		pthread_mutex_unlock(&mutex);
382186647Srwatson#endif
383155131Srwatson		return (-1);
384162503Srwatson	}
385185573Srwatson	if (strlen(dir) >= (size_t)len) {
386186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
387162503Srwatson		pthread_mutex_unlock(&mutex);
388186647Srwatson#endif
389155131Srwatson		return (-3);
390162503Srwatson	}
391185573Srwatson	strlcpy(name, dir, len);
392186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
393162503Srwatson	pthread_mutex_unlock(&mutex);
394186647Srwatson#endif
395155131Srwatson	return (ret);
396155131Srwatson}
397155131Srwatson
398155131Srwatson/*
399243750Srwatson * Return 1 if dist value is set to 'yes' or 'on'.
400243750Srwatson * Return 0 if dist value is set to something else.
401243750Srwatson * Return negative value on error.
402243750Srwatson */
403243750Srwatsonint
404243750Srwatsongetacdist(void)
405243750Srwatson{
406243750Srwatson	char *str;
407243750Srwatson	int ret;
408243750Srwatson
409243750Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
410243750Srwatson	pthread_mutex_lock(&mutex);
411243750Srwatson#endif
412243750Srwatson	setac_locked();
413243750Srwatson	if (getstrfromtype_locked(DIST_CONTROL_ENTRY, &str) < 0) {
414243750Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
415243750Srwatson		pthread_mutex_unlock(&mutex);
416243750Srwatson#endif
417243750Srwatson		return (-2);
418243750Srwatson	}
419243750Srwatson	if (str == NULL) {
420243750Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
421243750Srwatson		pthread_mutex_unlock(&mutex);
422243750Srwatson#endif
423243750Srwatson		return (0);
424243750Srwatson	}
425243750Srwatson	if (strcasecmp(str, "on") == 0 || strcasecmp(str, "yes") == 0)
426243750Srwatson		ret = 1;
427243750Srwatson	else
428243750Srwatson		ret = 0;
429243750Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
430243750Srwatson	pthread_mutex_unlock(&mutex);
431243750Srwatson#endif
432243750Srwatson	return (ret);
433243750Srwatson}
434243750Srwatson
435243750Srwatson/*
436162503Srwatson * Return the minimum free diskspace value from the audit control file.
437155131Srwatson */
438155131Srwatsonint
439155131Srwatsongetacmin(int *min_val)
440155131Srwatson{
441155131Srwatson	char *min;
442155131Srwatson
443186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
444155131Srwatson	pthread_mutex_lock(&mutex);
445186647Srwatson#endif
446162503Srwatson	setac_locked();
447155131Srwatson	if (getstrfromtype_locked(MINFREE_CONTROL_ENTRY, &min) < 0) {
448186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
449155131Srwatson		pthread_mutex_unlock(&mutex);
450186647Srwatson#endif
451155131Srwatson		return (-2);
452155131Srwatson	}
453162503Srwatson	if (min == NULL) {
454186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
455162503Srwatson		pthread_mutex_unlock(&mutex);
456186647Srwatson#endif
457243750Srwatson		return (-1);
458162503Srwatson	}
459155131Srwatson	*min_val = atoi(min);
460186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
461162503Srwatson	pthread_mutex_unlock(&mutex);
462186647Srwatson#endif
463155131Srwatson	return (0);
464155131Srwatson}
465155131Srwatson
466155131Srwatson/*
467162621Srwatson * Return the desired trail rotation size from the audit control file.
468162621Srwatson */
469162621Srwatsonint
470162621Srwatsongetacfilesz(size_t *filesz_val)
471162621Srwatson{
472189279Srwatson	char *str;
473189279Srwatson	size_t val;
474189279Srwatson	char mult;
475189279Srwatson	int nparsed;
476162621Srwatson
477186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
478162621Srwatson	pthread_mutex_lock(&mutex);
479186647Srwatson#endif
480162621Srwatson	setac_locked();
481189279Srwatson	if (getstrfromtype_locked(FILESZ_CONTROL_ENTRY, &str) < 0) {
482186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
483162621Srwatson		pthread_mutex_unlock(&mutex);
484186647Srwatson#endif
485162621Srwatson		return (-2);
486162621Srwatson	}
487189279Srwatson	if (str == NULL) {
488186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
489162621Srwatson		pthread_mutex_unlock(&mutex);
490186647Srwatson#endif
491162621Srwatson		errno = EINVAL;
492243750Srwatson		return (-1);
493162621Srwatson	}
494189279Srwatson
495189279Srwatson	/* Trim off any leading white space. */
496189279Srwatson	while (*str == ' ' || *str == '\t')
497189279Srwatson		str++;
498189279Srwatson
499189279Srwatson	nparsed = sscanf(str, "%ju%c", (uintmax_t *)&val, &mult);
500189279Srwatson
501189279Srwatson	switch (nparsed) {
502189279Srwatson	case 1:
503189279Srwatson		/* If no multiplier then assume 'B' (bytes). */
504189279Srwatson		mult = 'B';
505189279Srwatson		/* fall through */
506189279Srwatson	case 2:
507189279Srwatson		if (au_spacetobytes(filesz_val, val, mult) == 0)
508189279Srwatson			break;
509189279Srwatson		/* fall through */
510189279Srwatson	default:
511189279Srwatson		errno = EINVAL;
512186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
513162621Srwatson		pthread_mutex_unlock(&mutex);
514186647Srwatson#endif
515162621Srwatson		return (-1);
516162621Srwatson	}
517189279Srwatson
518162621Srwatson	/*
519162621Srwatson	 * The file size must either be 0 or >= MIN_AUDIT_FILE_SIZE.  0
520162621Srwatson	 * indicates no rotation size.
521162621Srwatson	 */
522189279Srwatson	if (*filesz_val < 0 || (*filesz_val > 0 &&
523189279Srwatson		*filesz_val < MIN_AUDIT_FILE_SIZE)) {
524186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
525162621Srwatson		pthread_mutex_unlock(&mutex);
526186647Srwatson#endif
527189279Srwatson		filesz_val = 0L;
528162621Srwatson		errno = EINVAL;
529162621Srwatson		return (-1);
530162621Srwatson	}
531186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
532162621Srwatson	pthread_mutex_unlock(&mutex);
533186647Srwatson#endif
534162621Srwatson	return (0);
535162621Srwatson}
536162621Srwatson
537243750Srwatsonstatic int
538243750Srwatsongetaccommon(const char *name, char *auditstr, int len)
539155131Srwatson{
540155131Srwatson	char *str;
541155131Srwatson
542186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
543155131Srwatson	pthread_mutex_lock(&mutex);
544186647Srwatson#endif
545162503Srwatson	setac_locked();
546243750Srwatson	if (getstrfromtype_locked(name, &str) < 0) {
547186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
548155131Srwatson		pthread_mutex_unlock(&mutex);
549186647Srwatson#endif
550155131Srwatson		return (-2);
551155131Srwatson	}
552162503Srwatson	if (str == NULL) {
553186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
554162503Srwatson		pthread_mutex_unlock(&mutex);
555186647Srwatson#endif
556243750Srwatson		return (-1);
557162503Srwatson	}
558185573Srwatson	if (strlen(str) >= (size_t)len) {
559186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
560162503Srwatson		pthread_mutex_unlock(&mutex);
561186647Srwatson#endif
562155131Srwatson		return (-3);
563162503Srwatson	}
564185573Srwatson	strlcpy(auditstr, str, len);
565186647Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
566162503Srwatson	pthread_mutex_unlock(&mutex);
567186647Srwatson#endif
568155131Srwatson	return (0);
569155131Srwatson}
570155131Srwatson
571155131Srwatson/*
572243750Srwatson * Return the system audit value from the audit contol file.
573243750Srwatson */
574243750Srwatsonint
575243750Srwatsongetacflg(char *auditstr, int len)
576243750Srwatson{
577243750Srwatson
578243750Srwatson	return (getaccommon(FLAGS_CONTROL_ENTRY, auditstr, len));
579243750Srwatson}
580243750Srwatson
581243750Srwatson/*
582155131Srwatson * Return the non attributable flags from the audit contol file.
583155131Srwatson */
584155131Srwatsonint
585155131Srwatsongetacna(char *auditstr, int len)
586155131Srwatson{
587155131Srwatson
588243750Srwatson	return (getaccommon(NA_CONTROL_ENTRY, auditstr, len));
589162503Srwatson}
590155131Srwatson
591162503Srwatson/*
592162503Srwatson * Return the policy field from the audit control file.
593162503Srwatson */
594162503Srwatsonint
595162503Srwatsongetacpol(char *auditstr, size_t len)
596162503Srwatson{
597162503Srwatson
598243750Srwatson	return (getaccommon(POLICY_CONTROL_ENTRY, auditstr, len));
599185573Srwatson}
600185573Srwatson
601185573Srwatsonint
602185573Srwatsongetachost(char *auditstr, size_t len)
603185573Srwatson{
604185573Srwatson
605243750Srwatson	return (getaccommon(HOST_CONTROL_ENTRY, auditstr, len));
606155131Srwatson}
607189279Srwatson
608189279Srwatson/*
609189279Srwatson * Set expiration conditions.
610189279Srwatson */
611189279Srwatsonstatic int
612189279Srwatsonsetexpirecond(time_t *age, size_t *size, u_long value, char mult)
613189279Srwatson{
614189279Srwatson
615189279Srwatson	if (isupper(mult) || ' ' == mult)
616189279Srwatson		return (au_spacetobytes(size, value, mult));
617189279Srwatson	else
618189279Srwatson		return (au_timetosec(age, value, mult));
619189279Srwatson}
620189279Srwatson
621189279Srwatson/*
622189279Srwatson * Return the expire-after field from the audit control file.
623189279Srwatson */
624189279Srwatsonint
625189279Srwatsongetacexpire(int *andflg, time_t *age, size_t *size)
626189279Srwatson{
627189279Srwatson	char *str;
628189279Srwatson	int nparsed;
629189279Srwatson	u_long val1, val2;
630189279Srwatson	char mult1, mult2;
631189279Srwatson	char andor[AU_LINE_MAX];
632189279Srwatson
633189279Srwatson	*age = 0L;
634189279Srwatson	*size = 0LL;
635189279Srwatson	*andflg = 0;
636189279Srwatson
637189279Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
638189279Srwatson	pthread_mutex_lock(&mutex);
639189279Srwatson#endif
640189279Srwatson	setac_locked();
641189279Srwatson	if (getstrfromtype_locked(EXPIRE_AFTER_CONTROL_ENTRY, &str) < 0) {
642189279Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
643189279Srwatson		pthread_mutex_unlock(&mutex);
644189279Srwatson#endif
645189279Srwatson		return (-2);
646189279Srwatson	}
647189279Srwatson	if (str == NULL) {
648189279Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
649189279Srwatson		pthread_mutex_unlock(&mutex);
650189279Srwatson#endif
651243750Srwatson		return (-1);
652189279Srwatson	}
653189279Srwatson
654189279Srwatson	/* First, trim off any leading white space. */
655189279Srwatson	while (*str == ' ' || *str == '\t')
656243750Srwatson		str++;
657189279Srwatson
658189279Srwatson	nparsed = sscanf(str, "%lu%c%[ \tadnorADNOR]%lu%c", &val1, &mult1,
659189279Srwatson	    andor, &val2, &mult2);
660189279Srwatson
661189279Srwatson	switch (nparsed) {
662189279Srwatson	case 1:
663189279Srwatson		/* If no multiplier then assume 'B' (Bytes). */
664189279Srwatson		mult1 = 'B';
665189279Srwatson		/* fall through */
666189279Srwatson	case 2:
667189279Srwatson		/* One expiration condition. */
668189279Srwatson		if (setexpirecond(age, size, val1, mult1) != 0) {
669189279Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
670189279Srwatson			pthread_mutex_unlock(&mutex);
671189279Srwatson#endif
672189279Srwatson			return (-1);
673189279Srwatson		}
674189279Srwatson		break;
675189279Srwatson
676189279Srwatson	case 5:
677189279Srwatson		/* Two expiration conditions. */
678243750Srwatson		if (setexpirecond(age, size, val1, mult1) != 0 ||
679189279Srwatson		    setexpirecond(age, size, val2, mult2) != 0) {
680189279Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
681189279Srwatson			pthread_mutex_unlock(&mutex);
682189279Srwatson#endif
683189279Srwatson			return (-1);
684189279Srwatson		}
685189279Srwatson		if (strcasestr(andor, "and") != NULL)
686189279Srwatson			*andflg = 1;
687189279Srwatson		else if (strcasestr(andor, "or") != NULL)
688189279Srwatson			*andflg = 0;
689189279Srwatson		else {
690189279Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
691189279Srwatson			pthread_mutex_unlock(&mutex);
692189279Srwatson#endif
693189279Srwatson			return (-1);
694189279Srwatson		}
695189279Srwatson		break;
696189279Srwatson
697189279Srwatson	default:
698189279Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
699189279Srwatson		pthread_mutex_unlock(&mutex);
700189279Srwatson#endif
701189279Srwatson		return (-1);
702189279Srwatson	}
703189279Srwatson
704189279Srwatson#ifdef HAVE_PTHREAD_MUTEX_LOCK
705189279Srwatson	pthread_mutex_unlock(&mutex);
706189279Srwatson#endif
707189279Srwatson	return (0);
708189279Srwatson}
709