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