17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5f8804e7fSgww * Common Development and Distribution License (the "License").
6f8804e7fSgww * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22f8804e7fSgww * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate /*
267c478bd9Sstevel@tonic-gate * get audit preselection mask values
277c478bd9Sstevel@tonic-gate */
287c478bd9Sstevel@tonic-gate
29f8804e7fSgww #include <ctype.h>
307c478bd9Sstevel@tonic-gate #include <stdio.h>
317c478bd9Sstevel@tonic-gate #include <string.h>
32f8804e7fSgww
33f8804e7fSgww #include <sys/errno.h>
347c478bd9Sstevel@tonic-gate #include <sys/types.h>
357c478bd9Sstevel@tonic-gate #include <bsm/audit.h>
367c478bd9Sstevel@tonic-gate #include <bsm/libbsm.h>
377c478bd9Sstevel@tonic-gate
38f8804e7fSgww #include <adt_xlate.h> /* adt_write_syslog */
397c478bd9Sstevel@tonic-gate
40f8804e7fSgww #define SUCCESS 0x1 /* '+' success mask */
41f8804e7fSgww #define FAILURE 0x2 /* '-' failure mask */
42f8804e7fSgww #define INVERSE 0x4 /* '^' invert the mask */
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate static int
match_class(char * s,char * prefix,uint_t m,int v)45f8804e7fSgww match_class(char *s, char *prefix, uint_t m, int v)
467c478bd9Sstevel@tonic-gate {
477c478bd9Sstevel@tonic-gate au_class_ent_t *p_class;
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate (void) strcat(s, prefix);
507c478bd9Sstevel@tonic-gate if (cacheauclass(&p_class, m) == 1) {
51f8804e7fSgww if (v == 0) {
52f8804e7fSgww (void) strncat(s, p_class->ac_name, AU_CLASS_NAME_MAX);
53f8804e7fSgww } else {
54f8804e7fSgww (void) strncat(s, p_class->ac_desc, AU_CLASS_DESC_MAX);
55f8804e7fSgww }
567c478bd9Sstevel@tonic-gate (void) strcat(s, ",");
577c478bd9Sstevel@tonic-gate return (0);
587c478bd9Sstevel@tonic-gate }
597c478bd9Sstevel@tonic-gate return (-1);
607c478bd9Sstevel@tonic-gate }
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate /*
637c478bd9Sstevel@tonic-gate * getauditflagschar() - convert bit flag to character string
647c478bd9Sstevel@tonic-gate *
657c478bd9Sstevel@tonic-gate * input: masks->am_success - audit on success
667c478bd9Sstevel@tonic-gate * masks->am_failure - audit on failure
677c478bd9Sstevel@tonic-gate * verbose - string format. 0 if short name; 1 if long name;
687c478bd9Sstevel@tonic-gate *
697c478bd9Sstevel@tonic-gate * output: auditstring - resultant audit string
707c478bd9Sstevel@tonic-gate *
717c478bd9Sstevel@tonic-gate * returns: 0 - entry read ok
727c478bd9Sstevel@tonic-gate * -1 - error
737c478bd9Sstevel@tonic-gate */
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate int
getauditflagschar(char * auditstring,au_mask_t * masks,int verbose)76f8804e7fSgww getauditflagschar(char *auditstring, au_mask_t *masks, int verbose)
777c478bd9Sstevel@tonic-gate {
787c478bd9Sstevel@tonic-gate char *prefix; /* +, -, or null */
797c478bd9Sstevel@tonic-gate unsigned int m; /* for masking with masks */
807c478bd9Sstevel@tonic-gate au_mask_t all; /* value for the string "all" */
817c478bd9Sstevel@tonic-gate int plus_all = 0; /* true if +all */
827c478bd9Sstevel@tonic-gate int minus_all = 0; /* true if -all */
837c478bd9Sstevel@tonic-gate int l;
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate /* initialize input buffer */
867c478bd9Sstevel@tonic-gate *auditstring = '\0';
877c478bd9Sstevel@tonic-gate /* no masks, no flags; we're outta here */
887c478bd9Sstevel@tonic-gate if ((masks->am_success == 0) && (masks->am_failure == 0)) {
897c478bd9Sstevel@tonic-gate if (match_class(auditstring, "", 0, verbose) != 0)
907c478bd9Sstevel@tonic-gate return (-1);
917c478bd9Sstevel@tonic-gate /* kludge to get rid of trailing comma */
927c478bd9Sstevel@tonic-gate l = strlen(auditstring) - 1;
93f8804e7fSgww if (auditstring[l] == ',')
947c478bd9Sstevel@tonic-gate auditstring[l] = '\0';
957c478bd9Sstevel@tonic-gate return (0);
967c478bd9Sstevel@tonic-gate }
977c478bd9Sstevel@tonic-gate /* Get the mask value for the string "all" */
987c478bd9Sstevel@tonic-gate all.am_success = 0;
997c478bd9Sstevel@tonic-gate all.am_failure = 0;
1007c478bd9Sstevel@tonic-gate if (getauditflagsbin("all", &all) != 0)
1017c478bd9Sstevel@tonic-gate return (-1);
1027c478bd9Sstevel@tonic-gate if (all.am_success == masks->am_success) {
1037c478bd9Sstevel@tonic-gate if (all.am_failure == masks->am_failure) {
1047c478bd9Sstevel@tonic-gate (void) strcat(auditstring, "all");
1057c478bd9Sstevel@tonic-gate return (0);
1067c478bd9Sstevel@tonic-gate }
1077c478bd9Sstevel@tonic-gate (void) strcat(auditstring, "+all,");
1087c478bd9Sstevel@tonic-gate plus_all = 1;
1097c478bd9Sstevel@tonic-gate } else if (all.am_failure == masks->am_failure) {
1107c478bd9Sstevel@tonic-gate (void) strcat(auditstring, "-all,");
1117c478bd9Sstevel@tonic-gate minus_all = 1;
1127c478bd9Sstevel@tonic-gate }
1137c478bd9Sstevel@tonic-gate for (m = (unsigned)0x80000000; m != 0; m >>= 1) {
1147c478bd9Sstevel@tonic-gate if (m & masks->am_success & masks->am_failure)
1157c478bd9Sstevel@tonic-gate prefix = plus_all ? "-" : (minus_all ? "+" : "");
1167c478bd9Sstevel@tonic-gate else if (m & masks->am_success)
1177c478bd9Sstevel@tonic-gate prefix = "+";
1187c478bd9Sstevel@tonic-gate else if (m & masks->am_failure)
1197c478bd9Sstevel@tonic-gate prefix = "-";
120f8804e7fSgww else
1217c478bd9Sstevel@tonic-gate continue;
1227c478bd9Sstevel@tonic-gate if (match_class(auditstring, prefix, m, verbose) != 0)
1237c478bd9Sstevel@tonic-gate return (-1);
1247c478bd9Sstevel@tonic-gate }
125f8804e7fSgww if (*(prefix = auditstring + strlen(auditstring) - 1) == ',')
1267c478bd9Sstevel@tonic-gate *prefix = '\0';
1277c478bd9Sstevel@tonic-gate return (0);
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate }
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate /*
132f8804e7fSgww * Audit flags:
1337c478bd9Sstevel@tonic-gate *
134f8804e7fSgww * [+ | - | ^ | ^+ | ^-]<classname>{,[+ | - | ^ | ^+ | ^-]<classname>}*
1357c478bd9Sstevel@tonic-gate *
136f8804e7fSgww * <classname>, add class mask to success and failure mask.
137f8804e7fSgww * +<classname>, add class mask only to success mask.
138f8804e7fSgww * -<classname>, add class mask only to failure mask.
139f8804e7fSgww * ^<classname>, remove class mask from success and failure mask.
140f8804e7fSgww * ^+<classname>, remove class mask from success mask.
141f8804e7fSgww * ^-<classname>, remove class mask from failure mask.
142f8804e7fSgww */
143f8804e7fSgww
144f8804e7fSgww /*
145f8804e7fSgww * __chkflags - check if the audit flags are valid for this system
1467c478bd9Sstevel@tonic-gate *
147f8804e7fSgww * Entry flags = audit flags string.
148f8804e7fSgww * cont = B_TRUE, continue parsing even if error.
149f8804e7fSgww * B_FALSE, return failure on error.
150f8804e7fSgww *
151f8804e7fSgww * Exit mask = audit mask as defined by flags.
152f8804e7fSgww *
153f8804e7fSgww * Return B_TRUE if no errors, or continue == B_TRUE.
154f8804e7fSgww * B_FALSE and if error != NULL, flags in error.
1557c478bd9Sstevel@tonic-gate */
1567c478bd9Sstevel@tonic-gate
157f8804e7fSgww boolean_t
__chkflags(char * flags,au_mask_t * mask,boolean_t cont,char ** error)158f8804e7fSgww __chkflags(char *flags, au_mask_t *mask, boolean_t cont, char **error)
1597c478bd9Sstevel@tonic-gate {
160f8804e7fSgww uint32_t prefix;
161f8804e7fSgww au_class_ent_t *class;
162f8804e7fSgww char name[AU_CLASS_NAME_MAX+1];
163f8804e7fSgww int i;
1647c478bd9Sstevel@tonic-gate
165f8804e7fSgww if (flags == NULL || mask == NULL) {
166f8804e7fSgww return (B_FALSE);
167f8804e7fSgww }
168f8804e7fSgww
169f8804e7fSgww mask->am_success = 0;
170f8804e7fSgww mask->am_failure = 0;
171f8804e7fSgww
172f8804e7fSgww while (*flags != '\0') {
173f8804e7fSgww prefix = (SUCCESS | FAILURE);
1747c478bd9Sstevel@tonic-gate
175f8804e7fSgww /* skip white space */
176f8804e7fSgww while (isspace(*flags)) {
177f8804e7fSgww flags++;
178f8804e7fSgww }
1797c478bd9Sstevel@tonic-gate
180*a0be388cSToomas Soome if (*flags == '\0') {
181f8804e7fSgww break;
182f8804e7fSgww }
183f8804e7fSgww if (error != NULL) {
184f8804e7fSgww /* save error pointer */
185f8804e7fSgww *error = flags;
186f8804e7fSgww }
187f8804e7fSgww
188f8804e7fSgww /* get the prefix */
189f8804e7fSgww if (*flags == '+') {
190f8804e7fSgww flags++;
191f8804e7fSgww prefix ^= FAILURE;
192f8804e7fSgww } else if (*flags == '-') {
193f8804e7fSgww flags++;
194f8804e7fSgww prefix ^= SUCCESS;
195f8804e7fSgww } else if (*flags == '^') {
196f8804e7fSgww flags++;
197f8804e7fSgww prefix |= INVERSE;
198f8804e7fSgww if (*flags == '+') {
199f8804e7fSgww flags++;
200f8804e7fSgww prefix ^= FAILURE;
201f8804e7fSgww } else if (*flags == '-') {
202f8804e7fSgww flags++;
203f8804e7fSgww prefix ^= SUCCESS;
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate }
2067c478bd9Sstevel@tonic-gate
207f8804e7fSgww /* get class name */
2087c478bd9Sstevel@tonic-gate
209f8804e7fSgww for (i = 0; (i < sizeof (name) - 1) &&
210f8804e7fSgww !(*flags == '\0' || *flags == ','); i++) {
211f8804e7fSgww name[i] = *flags++;
212f8804e7fSgww }
213f8804e7fSgww name[i++] = '\0';
214f8804e7fSgww if (*flags == ',') {
215f8804e7fSgww /* skip comma (',') */
216f8804e7fSgww flags++;
217f8804e7fSgww }
218f8804e7fSgww if (cacheauclassnam(&class, name) != 1) {
219f8804e7fSgww if (!cont) {
220f8804e7fSgww return (B_FALSE);
221f8804e7fSgww } else {
222f8804e7fSgww char msg[512];
2237c478bd9Sstevel@tonic-gate
224f8804e7fSgww (void) snprintf(msg, sizeof (msg), "invalid "
225f8804e7fSgww "audit flag %s", name);
226f8804e7fSgww adt_write_syslog(msg, EINVAL);
227f8804e7fSgww }
228f8804e7fSgww } else {
229f8804e7fSgww /* add class mask */
2307c478bd9Sstevel@tonic-gate
231f8804e7fSgww if ((prefix & (INVERSE | SUCCESS)) == SUCCESS) {
232f8804e7fSgww mask->am_success |= class->ac_class;
233f8804e7fSgww } else if ((prefix & (INVERSE | SUCCESS)) ==
234f8804e7fSgww (INVERSE | SUCCESS)) {
235f8804e7fSgww mask->am_success &= ~(class->ac_class);
2367c478bd9Sstevel@tonic-gate }
237f8804e7fSgww if ((prefix & (INVERSE | FAILURE)) == FAILURE) {
238f8804e7fSgww mask->am_failure |= class->ac_class;
239f8804e7fSgww } else if ((prefix & (INVERSE | FAILURE)) ==
240f8804e7fSgww (INVERSE | FAILURE)) {
241f8804e7fSgww mask->am_failure &= ~(class->ac_class);
2427c478bd9Sstevel@tonic-gate }
2437c478bd9Sstevel@tonic-gate }
244f8804e7fSgww }
2457c478bd9Sstevel@tonic-gate
246f8804e7fSgww return (B_TRUE);
247f8804e7fSgww }
2487c478bd9Sstevel@tonic-gate
249f8804e7fSgww /*
250f8804e7fSgww * getauditflagsbin() - converts character string to success and
251f8804e7fSgww * failure bit masks
252f8804e7fSgww *
253f8804e7fSgww * input: auditstring - audit string
254f8804e7fSgww *
255f8804e7fSgww * output: masks->am_success - audit on success
256f8804e7fSgww * masks->am_failure - audit on failure
257f8804e7fSgww *
258f8804e7fSgww * returns: 0 - ok
259f8804e7fSgww * -1 - error - string or mask NULL.
260f8804e7fSgww */
261f8804e7fSgww
262f8804e7fSgww int
getauditflagsbin(char * auditstring,au_mask_t * masks)263f8804e7fSgww getauditflagsbin(char *auditstring, au_mask_t *masks)
264f8804e7fSgww {
265f8804e7fSgww if (__chkflags(auditstring, masks, B_TRUE, NULL)) {
266f8804e7fSgww return (0);
267f8804e7fSgww }
268f8804e7fSgww return (-1);
2697c478bd9Sstevel@tonic-gate }
270