]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - contrib/openbsm/libbsm/bsm_flags.c
- Copy stable/10@296371 to releng/10.3 in preparation for 10.3-RC1
[FreeBSD/releng/10.3.git] / contrib / openbsm / libbsm / bsm_flags.c
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
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
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 }