bsm_control.c revision 162503
1/*
2 * Copyright (c) 2004 Apple Computer, Inc.
3 * Copyright (c) 2006 Robert N. M. Watson
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1.  Redistributions of source code must retain the above copyright
10 *     notice, this list of conditions and the following disclaimer.
11 * 2.  Redistributions in binary form must reproduce the above copyright
12 *     notice, this list of conditions and the following disclaimer in the
13 *     documentation and/or other materials provided with the distribution.
14 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 *     its contributors may be used to endorse or promote products derived
16 *     from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_control.c#15 $
31 */
32
33#include <bsm/libbsm.h>
34
35#include <errno.h>
36#include <string.h>
37#include <pthread.h>
38#include <stdio.h>
39#include <stdlib.h>
40
41#include <config/config.h>
42#ifndef HAVE_STRLCAT
43#include <compat/strlcat.h>
44#endif
45
46/*
47 * Parse the contents of the audit_control file to return the audit control
48 * parameters.  These static fields are protected by 'mutex'.
49 */
50static FILE	*fp = NULL;
51static char	linestr[AU_LINE_MAX];
52static char	*delim = ":";
53
54static char	inacdir = 0;
55static char	ptrmoved = 0;
56
57static pthread_mutex_t	mutex = PTHREAD_MUTEX_INITIALIZER;
58
59/*
60 * Returns the string value corresponding to the given label from the
61 * configuration file.
62 *
63 * Must be called with mutex held.
64 */
65static int
66getstrfromtype_locked(char *name, char **str)
67{
68	char *type, *nl;
69	char *tokptr;
70	char *last;
71
72	*str = NULL;
73
74	if ((fp == NULL) && ((fp = fopen(AUDIT_CONTROL_FILE, "r")) == NULL))
75		return (-1); /* Error */
76
77	while (1) {
78		if (fgets(linestr, AU_LINE_MAX, fp) == NULL) {
79			if (ferror(fp))
80				return (-1);
81			return (0);	/* EOF */
82		}
83
84		if (linestr[0] == '#')
85			continue;
86
87		/* Remove trailing new line character. */
88		if ((nl = strrchr(linestr, '\n')) != NULL)
89			*nl = '\0';
90
91		tokptr = linestr;
92		if ((type = strtok_r(tokptr, delim, &last)) != NULL) {
93			if (strcmp(name, type) == 0) {
94				/* Found matching name. */
95				*str = strtok_r(NULL, delim, &last);
96				if (*str == NULL) {
97					errno = EINVAL;
98					return (-1); /* Parse error in file */
99				}
100				return (0); /* Success */
101			}
102		}
103	}
104}
105
106/*
107 * Convert a policy to a string.  Return -1 on failure, or >= 0 representing
108 * the actual size of the string placed in the buffer (excluding terminating
109 * nul).
110 */
111ssize_t
112au_poltostr(long policy, size_t maxsize, char *buf)
113{
114	int first;
115
116	if (maxsize < 1)
117		return (-1);
118	first = 1;
119	buf[0] = '\0';
120
121	if (policy & AUDIT_CNT) {
122		if (strlcat(buf, "cnt", maxsize) >= maxsize)
123			return (-1);
124		first = 0;
125	}
126	if (policy & AUDIT_AHLT) {
127		if (!first) {
128			if (strlcat(buf, ",", maxsize) >= maxsize)
129				return (-1);
130		}
131		if (strlcat(buf, "ahlt", maxsize) >= maxsize)
132			return (-1);
133		first = 0;
134	}
135	if (policy & AUDIT_ARGV) {
136		if (!first) {
137			if (strlcat(buf, ",", maxsize) >= maxsize)
138				return (-1);
139		}
140		if (strlcat(buf, "argv", maxsize) >= maxsize)
141			return (-1);
142		first = 0;
143	}
144	if (policy & AUDIT_ARGE) {
145		if (!first) {
146			if (strlcat(buf, ",", maxsize) >= maxsize)
147				return (-1);
148		}
149		if (strlcat(buf, "arge", maxsize) >= maxsize)
150			return (-1);
151		first = 0;
152	}
153	if (policy & AUDIT_SEQ) {
154		if (!first) {
155			if (strlcat(buf, ",", maxsize) >= maxsize)
156				return (-1);
157		}
158		if (strlcat(buf, "seq", maxsize) >= maxsize)
159			return (-1);
160		first = 0;
161	}
162	if (policy & AUDIT_WINDATA) {
163		if (!first) {
164			if (strlcat(buf, ",", maxsize) >= maxsize)
165				return (-1);
166		}
167		if (strlcat(buf, "windata", maxsize) >= maxsize)
168			return (-1);
169		first = 0;
170	}
171	if (policy & AUDIT_USER) {
172		if (!first) {
173			if (strlcat(buf, ",", maxsize) >= maxsize)
174				return (-1);
175		}
176		if (strlcat(buf, "user", maxsize) >= maxsize)
177			return (-1);
178		first = 0;
179	}
180	if (policy & AUDIT_GROUP) {
181		if (!first) {
182			if (strlcat(buf, ",", maxsize) >= maxsize)
183				return (-1);
184		}
185		if (strlcat(buf, "group", maxsize) >= maxsize)
186			return (-1);
187		first = 0;
188	}
189	if (policy & AUDIT_TRAIL) {
190		if (!first) {
191			if (strlcat(buf, ",", maxsize) >= maxsize)
192				return (-1);
193		}
194		if (strlcat(buf, "trail", maxsize) >= maxsize)
195			return (-1);
196		first = 0;
197	}
198	if (policy & AUDIT_PATH) {
199		if (!first) {
200			if (strlcat(buf, ",", maxsize) >= maxsize)
201				return (-1);
202		}
203		if (strlcat(buf, "path", maxsize) >= maxsize)
204			return (-1);
205		first = 0;
206	}
207	if (policy & AUDIT_SCNT) {
208		if (!first) {
209			if (strlcat(buf, ",", maxsize) >= maxsize)
210				return (-1);
211		}
212		if (strlcat(buf, "scnt", maxsize) >= maxsize)
213			return (-1);
214		first = 0;
215	}
216	if (policy & AUDIT_PUBLIC) {
217		if (!first) {
218			if (strlcat(buf, ",", maxsize) >= maxsize)
219				return (-1);
220		}
221		if (strlcat(buf, "public", maxsize) >= maxsize)
222			return (-1);
223		first = 0;
224	}
225	if (policy & AUDIT_ZONENAME) {
226		if (!first) {
227			if (strlcat(buf, ",", maxsize) >= maxsize)
228				return (-1);
229		}
230		if (strlcat(buf, "zonename", maxsize) >= maxsize)
231			return (-1);
232		first = 0;
233	}
234	if (policy & AUDIT_PERZONE) {
235		if (!first) {
236			if (strlcat(buf, ",", maxsize) >= maxsize)
237				return (-1);
238		}
239		if (strlcat(buf, "perzone", maxsize) >= maxsize)
240			return (-1);
241		first = 0;
242	}
243	return (strlen(buf));
244}
245
246/*
247 * Convert a string to a policy.  Return -1 on failure (with errno EINVAL,
248 * ENOMEM) or 0 on success.
249 */
250int
251au_strtopol(const char *polstr, long *policy)
252{
253	char *bufp, *string;
254	char *buffer;
255
256	*policy = 0;
257	buffer = strdup(polstr);
258	if (buffer == NULL)
259		return (-1);
260
261	bufp = buffer;
262	while ((string = strsep(&bufp, ",")) != NULL) {
263		if (strcmp(string, "cnt") == 0)
264			*policy |= AUDIT_CNT;
265		else if (strcmp(string, "ahlt") == 0)
266			*policy |= AUDIT_AHLT;
267		else if (strcmp(string, "argv") == 0)
268			*policy |= AUDIT_ARGV;
269		else if (strcmp(string, "arge") == 0)
270			*policy |= AUDIT_ARGE;
271		else if (strcmp(string, "seq") == 0)
272			*policy |= AUDIT_SEQ;
273		else if (strcmp(string, "winau_fstat") == 0)
274			*policy |= AUDIT_WINDATA;
275		else if (strcmp(string, "user") == 0)
276			*policy |= AUDIT_USER;
277		else if (strcmp(string, "group") == 0)
278			*policy |= AUDIT_GROUP;
279		else if (strcmp(string, "trail") == 0)
280			*policy |= AUDIT_TRAIL;
281		else if (strcmp(string, "path") == 0)
282			*policy |= AUDIT_PATH;
283		else if (strcmp(string, "scnt") == 0)
284			*policy |= AUDIT_SCNT;
285		else if (strcmp(string, "public") == 0)
286			*policy |= AUDIT_PUBLIC;
287		else if (strcmp(string, "zonename") == 0)
288			*policy |= AUDIT_ZONENAME;
289		else if (strcmp(string, "perzone") == 0)
290			*policy |= AUDIT_PERZONE;
291		else {
292			free(buffer);
293			errno = EINVAL;
294			return (-1);
295		}
296	}
297	free(buffer);
298	return (0);
299}
300
301/*
302 * Rewind the file pointer to beginning.
303 */
304static void
305setac_locked(void)
306{
307
308	ptrmoved = 1;
309	if (fp != NULL)
310		fseek(fp, 0, SEEK_SET);
311}
312
313void
314setac(void)
315{
316
317	pthread_mutex_lock(&mutex);
318	setac_locked();
319	pthread_mutex_unlock(&mutex);
320}
321
322/*
323 * Close the audit_control file.
324 */
325void
326endac(void)
327{
328
329	pthread_mutex_lock(&mutex);
330	ptrmoved = 1;
331	if (fp != NULL) {
332		fclose(fp);
333		fp = NULL;
334	}
335	pthread_mutex_unlock(&mutex);
336}
337
338/*
339 * Return audit directory information from the audit control file.
340 */
341int
342getacdir(char *name, int len)
343{
344	char *dir;
345	int ret = 0;
346
347	/*
348	 * Check if another function was called between successive calls to
349	 * getacdir.
350	 */
351	pthread_mutex_lock(&mutex);
352	if (inacdir && ptrmoved) {
353		ptrmoved = 0;
354		if (fp != NULL)
355			fseek(fp, 0, SEEK_SET);
356		ret = 2;
357	}
358	if (getstrfromtype_locked(DIR_CONTROL_ENTRY, &dir) < 0) {
359		pthread_mutex_unlock(&mutex);
360		return (-2);
361	}
362	if (dir == NULL) {
363		pthread_mutex_unlock(&mutex);
364		return (-1);
365	}
366	if (strlen(dir) >= len) {
367		pthread_mutex_unlock(&mutex);
368		return (-3);
369	}
370	strcpy(name, dir);
371	pthread_mutex_unlock(&mutex);
372	return (ret);
373}
374
375/*
376 * Return the minimum free diskspace value from the audit control file.
377 */
378int
379getacmin(int *min_val)
380{
381	char *min;
382
383	pthread_mutex_lock(&mutex);
384	setac_locked();
385	if (getstrfromtype_locked(MINFREE_CONTROL_ENTRY, &min) < 0) {
386		pthread_mutex_unlock(&mutex);
387		return (-2);
388	}
389	if (min == NULL) {
390		pthread_mutex_unlock(&mutex);
391		return (1);
392	}
393	*min_val = atoi(min);
394	pthread_mutex_unlock(&mutex);
395	return (0);
396}
397
398/*
399 * Return the system audit value from the audit contol file.
400 */
401int
402getacflg(char *auditstr, int len)
403{
404	char *str;
405
406	pthread_mutex_lock(&mutex);
407	setac_locked();
408	if (getstrfromtype_locked(FLAGS_CONTROL_ENTRY, &str) < 0) {
409		pthread_mutex_unlock(&mutex);
410		return (-2);
411	}
412	if (str == NULL) {
413		pthread_mutex_unlock(&mutex);
414		return (1);
415	}
416	if (strlen(str) >= len) {
417		pthread_mutex_unlock(&mutex);
418		return (-3);
419	}
420	strcpy(auditstr, str);
421	pthread_mutex_unlock(&mutex);
422	return (0);
423}
424
425/*
426 * Return the non attributable flags from the audit contol file.
427 */
428int
429getacna(char *auditstr, int len)
430{
431	char *str;
432
433	pthread_mutex_lock(&mutex);
434	setac_locked();
435	if (getstrfromtype_locked(NA_CONTROL_ENTRY, &str) < 0) {
436		pthread_mutex_unlock(&mutex);
437		return (-2);
438	}
439	if (str == NULL) {
440		pthread_mutex_unlock(&mutex);
441		return (1);
442	}
443	if (strlen(str) >= len) {
444		pthread_mutex_unlock(&mutex);
445		return (-3);
446	}
447	strcpy(auditstr, str);
448	return (0);
449}
450
451/*
452 * Return the policy field from the audit control file.
453 */
454int
455getacpol(char *auditstr, size_t len)
456{
457	char *str;
458
459	pthread_mutex_lock(&mutex);
460	setac_locked();
461	if (getstrfromtype_locked(POLICY_CONTROL_ENTRY, &str) < 0) {
462		pthread_mutex_unlock(&mutex);
463		return (-2);
464	}
465	if (str == NULL) {
466		pthread_mutex_unlock(&mutex);
467		return (-1);
468	}
469	if (strlen(str) >= len) {
470		pthread_mutex_unlock(&mutex);
471		return (-3);
472	}
473	strcpy(auditstr, str);
474	pthread_mutex_unlock(&mutex);
475	return (0);
476}
477