xref: /freebsd/contrib/openbsm/libbsm/bsm_flags.c (revision b626f5a73a48f44a31a200291b141e1da408a2ff)
152267f74SRobert Watson /*-
252267f74SRobert Watson  * Copyright (c) 2004 Apple Inc.
3ca0716f5SRobert 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  */
30ca0716f5SRobert Watson 
3152267f74SRobert Watson #include <config/config.h>
3252267f74SRobert Watson 
33ca0716f5SRobert Watson #include <bsm/libbsm.h>
34ca0716f5SRobert Watson 
35ca0716f5SRobert Watson #include <errno.h>
36ca0716f5SRobert Watson #include <stdio.h>
37ca0716f5SRobert Watson #include <string.h>
38ca0716f5SRobert Watson 
3952267f74SRobert Watson #ifndef HAVE_STRLCPY
4052267f74SRobert Watson #include <compat/strlcpy.h>
4152267f74SRobert Watson #endif
4252267f74SRobert Watson 
43ca0716f5SRobert Watson static const char	*flagdelim = ",";
44ca0716f5SRobert Watson 
45ca0716f5SRobert Watson /*
46ca0716f5SRobert Watson  * Convert the character representation of audit values into the au_mask_t
47ca0716f5SRobert Watson  * field.
48ca0716f5SRobert Watson  */
49ca0716f5SRobert Watson int
getauditflagsbin(char * auditstr,au_mask_t * masks)50ca0716f5SRobert Watson getauditflagsbin(char *auditstr, au_mask_t *masks)
51ca0716f5SRobert Watson {
52ca0716f5SRobert Watson 	char class_ent_name[AU_CLASS_NAME_MAX];
53ca0716f5SRobert Watson 	char class_ent_desc[AU_CLASS_DESC_MAX];
54ca0716f5SRobert Watson 	struct au_class_ent c;
55ca0716f5SRobert Watson 	char *tok;
56ca0716f5SRobert Watson 	char sel, sub;
57ca0716f5SRobert Watson 	char *last;
58ca0716f5SRobert Watson 
59ca0716f5SRobert Watson 	bzero(&c, sizeof(c));
60ca0716f5SRobert Watson 	bzero(class_ent_name, sizeof(class_ent_name));
61ca0716f5SRobert Watson 	bzero(class_ent_desc, sizeof(class_ent_desc));
62ca0716f5SRobert Watson 	c.ac_name = class_ent_name;
63ca0716f5SRobert Watson 	c.ac_desc = class_ent_desc;
64ca0716f5SRobert Watson 
65ca0716f5SRobert Watson 	masks->am_success = 0;
66ca0716f5SRobert Watson 	masks->am_failure = 0;
67ca0716f5SRobert Watson 
68ca0716f5SRobert Watson 	tok = strtok_r(auditstr, flagdelim, &last);
69ca0716f5SRobert Watson 	while (tok != NULL) {
70ca0716f5SRobert Watson 		/* Check for the events that should not be audited. */
71ca0716f5SRobert Watson 		if (tok[0] == '^') {
72ca0716f5SRobert Watson 			sub = 1;
73ca0716f5SRobert Watson 			tok++;
74ca0716f5SRobert Watson 		} else
75ca0716f5SRobert Watson 			sub = 0;
76ca0716f5SRobert Watson 
77ca0716f5SRobert Watson 		/* Check for the events to be audited for success. */
78ca0716f5SRobert Watson 		if (tok[0] == '+') {
79ca0716f5SRobert Watson 			sel = AU_PRS_SUCCESS;
80ca0716f5SRobert Watson 			tok++;
81ca0716f5SRobert Watson 		} else if (tok[0] == '-') {
82ca0716f5SRobert Watson 			sel = AU_PRS_FAILURE;
83ca0716f5SRobert Watson 			tok++;
84ca0716f5SRobert Watson 		} else
85ca0716f5SRobert Watson 			sel = AU_PRS_BOTH;
86ca0716f5SRobert Watson 
87ca0716f5SRobert Watson 		if ((getauclassnam_r(&c, tok)) != NULL) {
88ca0716f5SRobert Watson 			if (sub)
89ca0716f5SRobert Watson 				SUB_FROM_MASK(masks, c.ac_class, sel);
90ca0716f5SRobert Watson 			else
91ca0716f5SRobert Watson 				ADD_TO_MASK(masks, c.ac_class, sel);
92ca0716f5SRobert Watson 		} else {
93ca0716f5SRobert Watson 			errno = EINVAL;
94ca0716f5SRobert Watson 			return (-1);
95ca0716f5SRobert Watson 		}
96ca0716f5SRobert Watson 
97ca0716f5SRobert Watson 		/* Get the next class. */
98ca0716f5SRobert Watson 		tok = strtok_r(NULL, flagdelim, &last);
99ca0716f5SRobert Watson 	}
100ca0716f5SRobert Watson 	return (0);
101ca0716f5SRobert Watson }
102ca0716f5SRobert Watson 
103ca0716f5SRobert Watson /*
104ca0716f5SRobert Watson  * Convert the au_mask_t fields into a string value.  If verbose is non-zero
105ca0716f5SRobert Watson  * the long flag names are used else the short (2-character)flag names are
106ca0716f5SRobert Watson  * used.
107ca0716f5SRobert Watson  *
108ca0716f5SRobert Watson  * XXXRW: If bits are specified that are not matched by any class, they are
109ca0716f5SRobert Watson  * omitted rather than rejected with EINVAL.
110ca0716f5SRobert Watson  *
111ca0716f5SRobert Watson  * XXXRW: This is not thread-safe as it relies on atomicity between
112ca0716f5SRobert Watson  * setauclass() and sequential calls to getauclassent().  This could be
113ca0716f5SRobert Watson  * fixed by iterating through the bitmask fields rather than iterating
114ca0716f5SRobert Watson  * through the classes.
115ca0716f5SRobert Watson  */
116ca0716f5SRobert Watson int
getauditflagschar(char * auditstr,au_mask_t * masks,int verbose)117ca0716f5SRobert Watson getauditflagschar(char *auditstr, au_mask_t *masks, int verbose)
118ca0716f5SRobert Watson {
119ca0716f5SRobert Watson 	char class_ent_name[AU_CLASS_NAME_MAX];
120ca0716f5SRobert Watson 	char class_ent_desc[AU_CLASS_DESC_MAX];
121ca0716f5SRobert Watson 	struct au_class_ent c;
122ca0716f5SRobert Watson 	char *strptr = auditstr;
123ca0716f5SRobert Watson 	u_char sel;
124ca0716f5SRobert Watson 
125ca0716f5SRobert Watson 	bzero(&c, sizeof(c));
126ca0716f5SRobert Watson 	bzero(class_ent_name, sizeof(class_ent_name));
127ca0716f5SRobert Watson 	bzero(class_ent_desc, sizeof(class_ent_desc));
128ca0716f5SRobert Watson 	c.ac_name = class_ent_name;
129ca0716f5SRobert Watson 	c.ac_desc = class_ent_desc;
130ca0716f5SRobert Watson 
131ca0716f5SRobert Watson 	/*
132ca0716f5SRobert Watson 	 * Enumerate the class entries, check if each is selected in either
133ca0716f5SRobert Watson 	 * the success or failure masks.
134ca0716f5SRobert Watson 	 */
135ca0716f5SRobert Watson 	setauclass();
136ca0716f5SRobert Watson 	while ((getauclassent_r(&c)) != NULL) {
137ca0716f5SRobert Watson 		sel = 0;
138ca0716f5SRobert Watson 
139ca0716f5SRobert Watson 		/* Dont do anything for class = no. */
140ca0716f5SRobert Watson 		if (c.ac_class == 0)
141ca0716f5SRobert Watson 			continue;
142ca0716f5SRobert Watson 
143ca0716f5SRobert Watson 		sel |= ((c.ac_class & masks->am_success) == c.ac_class) ?
144ca0716f5SRobert Watson 		    AU_PRS_SUCCESS : 0;
145ca0716f5SRobert Watson 		sel |= ((c.ac_class & masks->am_failure) == c.ac_class) ?
146ca0716f5SRobert Watson 		    AU_PRS_FAILURE : 0;
147ca0716f5SRobert Watson 
148ca0716f5SRobert Watson 		/*
149ca0716f5SRobert Watson 		 * No prefix should be attached if both success and failure
150ca0716f5SRobert Watson 		 * are selected.
151ca0716f5SRobert Watson 		 */
152ca0716f5SRobert Watson 		if ((sel & AU_PRS_BOTH) == 0) {
153ca0716f5SRobert Watson 			if ((sel & AU_PRS_SUCCESS) != 0) {
154ca0716f5SRobert Watson 				*strptr = '+';
155ca0716f5SRobert Watson 				strptr = strptr + 1;
156ca0716f5SRobert Watson 			} else if ((sel & AU_PRS_FAILURE) != 0) {
157ca0716f5SRobert Watson 				*strptr = '-';
158ca0716f5SRobert Watson 				strptr = strptr + 1;
159ca0716f5SRobert Watson 			}
160ca0716f5SRobert Watson 		}
161ca0716f5SRobert Watson 
162ca0716f5SRobert Watson 		if (sel != 0) {
163ca0716f5SRobert Watson 			if (verbose) {
16452267f74SRobert Watson 				strlcpy(strptr, c.ac_desc, AU_CLASS_DESC_MAX);
165ca0716f5SRobert Watson 				strptr += strlen(c.ac_desc);
166ca0716f5SRobert Watson 			} else {
16752267f74SRobert Watson 				strlcpy(strptr, c.ac_name, AU_CLASS_NAME_MAX);
168ca0716f5SRobert Watson 				strptr += strlen(c.ac_name);
169ca0716f5SRobert Watson 			}
170ca0716f5SRobert Watson 			*strptr = ','; /* delimiter */
171ca0716f5SRobert Watson 			strptr = strptr + 1;
172ca0716f5SRobert Watson 		}
173ca0716f5SRobert Watson 	}
174ca0716f5SRobert Watson 
175ca0716f5SRobert Watson 	/* Overwrite the last delimiter with the string terminator. */
176ca0716f5SRobert Watson 	if (strptr != auditstr)
177ca0716f5SRobert Watson 		*(strptr-1) = '\0';
178ca0716f5SRobert Watson 
179ca0716f5SRobert Watson 	return (0);
180ca0716f5SRobert Watson }
181