1185573Srwatson/*-
2185573Srwatson * Copyright (c) 2004 Apple Inc.
3155131Srwatson * 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 *
30185573Srwatson * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_flags.c#16 $
31155131Srwatson */
32155131Srwatson
33185573Srwatson#include <config/config.h>
34185573Srwatson
35155131Srwatson#include <bsm/libbsm.h>
36155131Srwatson
37155131Srwatson#include <errno.h>
38155131Srwatson#include <stdio.h>
39155131Srwatson#include <string.h>
40155131Srwatson
41185573Srwatson#ifndef HAVE_STRLCPY
42185573Srwatson#include <compat/strlcpy.h>
43185573Srwatson#endif
44185573Srwatson
45155131Srwatsonstatic const char	*flagdelim = ",";
46155131Srwatson
47155131Srwatson/*
48155131Srwatson * Convert the character representation of audit values into the au_mask_t
49155131Srwatson * field.
50155131Srwatson */
51155131Srwatsonint
52155131Srwatsongetauditflagsbin(char *auditstr, au_mask_t *masks)
53155131Srwatson{
54155131Srwatson	char class_ent_name[AU_CLASS_NAME_MAX];
55155131Srwatson	char class_ent_desc[AU_CLASS_DESC_MAX];
56155131Srwatson	struct au_class_ent c;
57155131Srwatson	char *tok;
58155131Srwatson	char sel, sub;
59155131Srwatson	char *last;
60155131Srwatson
61155131Srwatson	bzero(&c, sizeof(c));
62155131Srwatson	bzero(class_ent_name, sizeof(class_ent_name));
63155131Srwatson	bzero(class_ent_desc, sizeof(class_ent_desc));
64155131Srwatson	c.ac_name = class_ent_name;
65155131Srwatson	c.ac_desc = class_ent_desc;
66155131Srwatson
67155131Srwatson	masks->am_success = 0;
68155131Srwatson	masks->am_failure = 0;
69155131Srwatson
70155131Srwatson	tok = strtok_r(auditstr, flagdelim, &last);
71155131Srwatson	while (tok != NULL) {
72155131Srwatson		/* Check for the events that should not be audited. */
73155131Srwatson		if (tok[0] == '^') {
74155131Srwatson			sub = 1;
75155131Srwatson			tok++;
76155131Srwatson		} else
77155131Srwatson			sub = 0;
78155131Srwatson
79155131Srwatson		/* Check for the events to be audited for success. */
80155131Srwatson		if (tok[0] == '+') {
81155131Srwatson			sel = AU_PRS_SUCCESS;
82155131Srwatson			tok++;
83155131Srwatson		} else if (tok[0] == '-') {
84155131Srwatson			sel = AU_PRS_FAILURE;
85155131Srwatson			tok++;
86155131Srwatson		} else
87155131Srwatson			sel = AU_PRS_BOTH;
88155131Srwatson
89155131Srwatson		if ((getauclassnam_r(&c, tok)) != NULL) {
90155131Srwatson			if (sub)
91155131Srwatson				SUB_FROM_MASK(masks, c.ac_class, sel);
92155131Srwatson			else
93155131Srwatson				ADD_TO_MASK(masks, c.ac_class, sel);
94155131Srwatson		} else {
95155131Srwatson			errno = EINVAL;
96155131Srwatson			return (-1);
97155131Srwatson		}
98155131Srwatson
99155131Srwatson		/* Get the next class. */
100155131Srwatson		tok = strtok_r(NULL, flagdelim, &last);
101155131Srwatson	}
102155131Srwatson	return (0);
103155131Srwatson}
104155131Srwatson
105155131Srwatson/*
106155131Srwatson * Convert the au_mask_t fields into a string value.  If verbose is non-zero
107155131Srwatson * the long flag names are used else the short (2-character)flag names are
108155131Srwatson * used.
109155131Srwatson *
110155131Srwatson * XXXRW: If bits are specified that are not matched by any class, they are
111155131Srwatson * omitted rather than rejected with EINVAL.
112155131Srwatson *
113155131Srwatson * XXXRW: This is not thread-safe as it relies on atomicity between
114155131Srwatson * setauclass() and sequential calls to getauclassent().  This could be
115155131Srwatson * fixed by iterating through the bitmask fields rather than iterating
116155131Srwatson * through the classes.
117155131Srwatson */
118155131Srwatsonint
119155131Srwatsongetauditflagschar(char *auditstr, au_mask_t *masks, int verbose)
120155131Srwatson{
121155131Srwatson	char class_ent_name[AU_CLASS_NAME_MAX];
122155131Srwatson	char class_ent_desc[AU_CLASS_DESC_MAX];
123155131Srwatson	struct au_class_ent c;
124155131Srwatson	char *strptr = auditstr;
125155131Srwatson	u_char sel;
126155131Srwatson
127155131Srwatson	bzero(&c, sizeof(c));
128155131Srwatson	bzero(class_ent_name, sizeof(class_ent_name));
129155131Srwatson	bzero(class_ent_desc, sizeof(class_ent_desc));
130155131Srwatson	c.ac_name = class_ent_name;
131155131Srwatson	c.ac_desc = class_ent_desc;
132155131Srwatson
133155131Srwatson	/*
134155131Srwatson	 * Enumerate the class entries, check if each is selected in either
135155131Srwatson	 * the success or failure masks.
136155131Srwatson	 */
137155131Srwatson	setauclass();
138155131Srwatson	while ((getauclassent_r(&c)) != NULL) {
139155131Srwatson		sel = 0;
140155131Srwatson
141155131Srwatson		/* Dont do anything for class = no. */
142155131Srwatson		if (c.ac_class == 0)
143155131Srwatson			continue;
144155131Srwatson
145155131Srwatson		sel |= ((c.ac_class & masks->am_success) == c.ac_class) ?
146155131Srwatson		    AU_PRS_SUCCESS : 0;
147155131Srwatson		sel |= ((c.ac_class & masks->am_failure) == c.ac_class) ?
148155131Srwatson		    AU_PRS_FAILURE : 0;
149155131Srwatson
150155131Srwatson		/*
151155131Srwatson		 * No prefix should be attached if both success and failure
152155131Srwatson		 * are selected.
153155131Srwatson		 */
154155131Srwatson		if ((sel & AU_PRS_BOTH) == 0) {
155155131Srwatson			if ((sel & AU_PRS_SUCCESS) != 0) {
156155131Srwatson				*strptr = '+';
157155131Srwatson				strptr = strptr + 1;
158155131Srwatson			} else if ((sel & AU_PRS_FAILURE) != 0) {
159155131Srwatson				*strptr = '-';
160155131Srwatson				strptr = strptr + 1;
161155131Srwatson			}
162155131Srwatson		}
163155131Srwatson
164155131Srwatson		if (sel != 0) {
165155131Srwatson			if (verbose) {
166185573Srwatson				strlcpy(strptr, c.ac_desc, AU_CLASS_DESC_MAX);
167155131Srwatson				strptr += strlen(c.ac_desc);
168155131Srwatson			} else {
169185573Srwatson				strlcpy(strptr, c.ac_name, AU_CLASS_NAME_MAX);
170155131Srwatson				strptr += strlen(c.ac_name);
171155131Srwatson			}
172155131Srwatson			*strptr = ','; /* delimiter */
173155131Srwatson			strptr = strptr + 1;
174155131Srwatson		}
175155131Srwatson	}
176155131Srwatson
177155131Srwatson	/* Overwrite the last delimiter with the string terminator. */
178155131Srwatson	if (strptr != auditstr)
179155131Srwatson		*(strptr-1) = '\0';
180155131Srwatson
181155131Srwatson	return (0);
182155131Srwatson}
183