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