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