xref: /onnv-gate/usr/src/lib/libbsm/common/getauditflags.c (revision 12326:7a0184667fca)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*12326Sgww@eng.sun.com  * Common Development and Distribution License (the "License").
6*12326Sgww@eng.sun.com  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*12326Sgww@eng.sun.com  * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate /*
260Sstevel@tonic-gate  * get audit preselection mask values
270Sstevel@tonic-gate  */
280Sstevel@tonic-gate 
29*12326Sgww@eng.sun.com #include <ctype.h>
300Sstevel@tonic-gate #include <stdio.h>
310Sstevel@tonic-gate #include <string.h>
32*12326Sgww@eng.sun.com 
33*12326Sgww@eng.sun.com #include <sys/errno.h>
340Sstevel@tonic-gate #include <sys/types.h>
350Sstevel@tonic-gate #include <bsm/audit.h>
360Sstevel@tonic-gate #include <bsm/libbsm.h>
370Sstevel@tonic-gate 
38*12326Sgww@eng.sun.com #include <adt_xlate.h>		/* adt_write_syslog */
390Sstevel@tonic-gate 
40*12326Sgww@eng.sun.com #define	SUCCESS 0x1		/* '+' success mask */
41*12326Sgww@eng.sun.com #define	FAILURE	0x2		/* '-' failure mask */
42*12326Sgww@eng.sun.com #define	INVERSE	0x4		/* '^' invert the mask */
430Sstevel@tonic-gate 
440Sstevel@tonic-gate static int
match_class(char * s,char * prefix,uint_t m,int v)45*12326Sgww@eng.sun.com match_class(char *s, char *prefix, uint_t m, int v)
460Sstevel@tonic-gate {
470Sstevel@tonic-gate 	au_class_ent_t *p_class;
480Sstevel@tonic-gate 
490Sstevel@tonic-gate 	(void) strcat(s, prefix);
500Sstevel@tonic-gate 	if (cacheauclass(&p_class, m) == 1) {
51*12326Sgww@eng.sun.com 		if (v == 0) {
52*12326Sgww@eng.sun.com 			(void) strncat(s, p_class->ac_name, AU_CLASS_NAME_MAX);
53*12326Sgww@eng.sun.com 		} else {
54*12326Sgww@eng.sun.com 			(void) strncat(s, p_class->ac_desc, AU_CLASS_DESC_MAX);
55*12326Sgww@eng.sun.com 		}
560Sstevel@tonic-gate 		(void) strcat(s, ",");
570Sstevel@tonic-gate 		return (0);
580Sstevel@tonic-gate 	}
590Sstevel@tonic-gate 	return (-1);
600Sstevel@tonic-gate }
610Sstevel@tonic-gate 
620Sstevel@tonic-gate /*
630Sstevel@tonic-gate  * getauditflagschar() - convert bit flag to character string
640Sstevel@tonic-gate  *
650Sstevel@tonic-gate  * input:	masks->am_success - audit on success
660Sstevel@tonic-gate  *		masks->am_failure - audit on failure
670Sstevel@tonic-gate  *		verbose - string format. 0 if short name; 1 if long name;
680Sstevel@tonic-gate  *
690Sstevel@tonic-gate  * output: auditstring - resultant audit string
700Sstevel@tonic-gate  *
710Sstevel@tonic-gate  * returns: 	0 - entry read ok
720Sstevel@tonic-gate  *		-1 - error
730Sstevel@tonic-gate  */
740Sstevel@tonic-gate 
750Sstevel@tonic-gate int
getauditflagschar(char * auditstring,au_mask_t * masks,int verbose)76*12326Sgww@eng.sun.com getauditflagschar(char *auditstring, au_mask_t *masks, int verbose)
770Sstevel@tonic-gate {
780Sstevel@tonic-gate 	char	*prefix;		/* +, -, or null */
790Sstevel@tonic-gate 	unsigned int	m;		/* for masking with masks */
800Sstevel@tonic-gate 	au_mask_t all; 		/* value for the string "all" */
810Sstevel@tonic-gate 	int	plus_all = 0;	/* true if +all */
820Sstevel@tonic-gate 	int	minus_all = 0;	/* true if -all */
830Sstevel@tonic-gate 	int	l;
840Sstevel@tonic-gate 
850Sstevel@tonic-gate 	/* initialize input buffer */
860Sstevel@tonic-gate 	*auditstring = '\0';
870Sstevel@tonic-gate 	/* no masks, no flags; we're outta here */
880Sstevel@tonic-gate 	if ((masks->am_success == 0) && (masks->am_failure == 0)) {
890Sstevel@tonic-gate 		if (match_class(auditstring, "", 0, verbose) != 0)
900Sstevel@tonic-gate 			return (-1);
910Sstevel@tonic-gate 		/* kludge to get rid of trailing comma */
920Sstevel@tonic-gate 		l = strlen(auditstring) - 1;
93*12326Sgww@eng.sun.com 		if (auditstring[l] == ',')
940Sstevel@tonic-gate 			auditstring[l] = '\0';
950Sstevel@tonic-gate 		return (0);
960Sstevel@tonic-gate 	}
970Sstevel@tonic-gate 	/* Get the mask value for the string "all" */
980Sstevel@tonic-gate 	all.am_success = 0;
990Sstevel@tonic-gate 	all.am_failure = 0;
1000Sstevel@tonic-gate 	if (getauditflagsbin("all", &all) != 0)
1010Sstevel@tonic-gate 		return (-1);
1020Sstevel@tonic-gate 	if (all.am_success == masks->am_success) {
1030Sstevel@tonic-gate 		if (all.am_failure == masks->am_failure) {
1040Sstevel@tonic-gate 			(void) strcat(auditstring, "all");
1050Sstevel@tonic-gate 			return (0);
1060Sstevel@tonic-gate 		}
1070Sstevel@tonic-gate 		(void) strcat(auditstring, "+all,");
1080Sstevel@tonic-gate 		plus_all = 1;
1090Sstevel@tonic-gate 	} else if (all.am_failure == masks->am_failure) {
1100Sstevel@tonic-gate 		(void) strcat(auditstring, "-all,");
1110Sstevel@tonic-gate 		minus_all = 1;
1120Sstevel@tonic-gate 	}
1130Sstevel@tonic-gate 	for (m = (unsigned)0x80000000; m != 0; m >>= 1) {
1140Sstevel@tonic-gate 		if (m & masks->am_success & masks->am_failure)
1150Sstevel@tonic-gate 			prefix = plus_all ? "-" : (minus_all ? "+" : "");
1160Sstevel@tonic-gate 		else if (m & masks->am_success)
1170Sstevel@tonic-gate 			prefix = "+";
1180Sstevel@tonic-gate 		else if (m & masks->am_failure)
1190Sstevel@tonic-gate 			prefix = "-";
120*12326Sgww@eng.sun.com 		else
1210Sstevel@tonic-gate 			continue;
1220Sstevel@tonic-gate 		if (match_class(auditstring, prefix, m, verbose) != 0)
1230Sstevel@tonic-gate 			return (-1);
1240Sstevel@tonic-gate 	}
125*12326Sgww@eng.sun.com 	if (*(prefix = auditstring + strlen(auditstring) - 1) == ',')
1260Sstevel@tonic-gate 		*prefix = '\0';
1270Sstevel@tonic-gate 	return (0);
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate /*
132*12326Sgww@eng.sun.com  *  Audit flags:
133*12326Sgww@eng.sun.com  *
134*12326Sgww@eng.sun.com  *	[+ | - | ^ | ^+ | ^-]<classname>{,[+ | - | ^ | ^+ | ^-]<classname>}*
135*12326Sgww@eng.sun.com  *
136*12326Sgww@eng.sun.com  *	  <classname>, add class mask to success and failure mask.
137*12326Sgww@eng.sun.com  *	 +<classname>, add class mask only to success mask.
138*12326Sgww@eng.sun.com  *	 -<classname>, add class mask only to failure mask.
139*12326Sgww@eng.sun.com  *	 ^<classname>, remove class mask from success and failure mask.
140*12326Sgww@eng.sun.com  *	^+<classname>, remove class mask from success mask.
141*12326Sgww@eng.sun.com  *	^-<classname>, remove class mask from failure mask.
142*12326Sgww@eng.sun.com  */
143*12326Sgww@eng.sun.com 
144*12326Sgww@eng.sun.com /*
145*12326Sgww@eng.sun.com  * __chkflags - check if the audit flags are valid for this system
146*12326Sgww@eng.sun.com  *
147*12326Sgww@eng.sun.com  *	Entry	flags = audit flags string.
148*12326Sgww@eng.sun.com  *		cont  = B_TRUE, continue parsing even if error.
149*12326Sgww@eng.sun.com  *			B_FALSE, return failure on error.
150*12326Sgww@eng.sun.com  *
151*12326Sgww@eng.sun.com  *	Exit	mask = audit mask as defined by flags.
152*12326Sgww@eng.sun.com  *
153*12326Sgww@eng.sun.com  *	Return	B_TRUE if no errors, or continue == B_TRUE.
154*12326Sgww@eng.sun.com  *		B_FALSE and if error != NULL, flags in error.
155*12326Sgww@eng.sun.com  */
156*12326Sgww@eng.sun.com 
157*12326Sgww@eng.sun.com boolean_t
__chkflags(char * flags,au_mask_t * mask,boolean_t cont,char ** error)158*12326Sgww@eng.sun.com __chkflags(char *flags, au_mask_t *mask, boolean_t cont, char **error)
159*12326Sgww@eng.sun.com {
160*12326Sgww@eng.sun.com 	uint32_t	prefix;
161*12326Sgww@eng.sun.com 	au_class_ent_t	*class;
162*12326Sgww@eng.sun.com 	char		name[AU_CLASS_NAME_MAX+1];
163*12326Sgww@eng.sun.com 	int		i;
164*12326Sgww@eng.sun.com 
165*12326Sgww@eng.sun.com 	if (flags == NULL || mask == NULL) {
166*12326Sgww@eng.sun.com 		return (B_FALSE);
167*12326Sgww@eng.sun.com 	}
168*12326Sgww@eng.sun.com 
169*12326Sgww@eng.sun.com 	mask->am_success = 0;
170*12326Sgww@eng.sun.com 	mask->am_failure = 0;
171*12326Sgww@eng.sun.com 
172*12326Sgww@eng.sun.com 	while (*flags != '\0') {
173*12326Sgww@eng.sun.com 		prefix = (SUCCESS | FAILURE);
174*12326Sgww@eng.sun.com 
175*12326Sgww@eng.sun.com 		/* skip white space */
176*12326Sgww@eng.sun.com 		while (isspace(*flags)) {
177*12326Sgww@eng.sun.com 			flags++;
178*12326Sgww@eng.sun.com 		}
179*12326Sgww@eng.sun.com 
180*12326Sgww@eng.sun.com 		if (flags == '\0') {
181*12326Sgww@eng.sun.com 			break;
182*12326Sgww@eng.sun.com 		}
183*12326Sgww@eng.sun.com 		if (error != NULL) {
184*12326Sgww@eng.sun.com 			/* save error pointer */
185*12326Sgww@eng.sun.com 			*error = flags;
186*12326Sgww@eng.sun.com 		}
187*12326Sgww@eng.sun.com 
188*12326Sgww@eng.sun.com 		/* get the prefix */
189*12326Sgww@eng.sun.com 		if (*flags == '+') {
190*12326Sgww@eng.sun.com 			flags++;
191*12326Sgww@eng.sun.com 			prefix ^= FAILURE;
192*12326Sgww@eng.sun.com 		} else if (*flags == '-') {
193*12326Sgww@eng.sun.com 			flags++;
194*12326Sgww@eng.sun.com 			prefix ^= SUCCESS;
195*12326Sgww@eng.sun.com 		} else if (*flags == '^') {
196*12326Sgww@eng.sun.com 			flags++;
197*12326Sgww@eng.sun.com 			prefix |= INVERSE;
198*12326Sgww@eng.sun.com 			if (*flags == '+') {
199*12326Sgww@eng.sun.com 				flags++;
200*12326Sgww@eng.sun.com 				prefix ^= FAILURE;
201*12326Sgww@eng.sun.com 			} else if (*flags == '-') {
202*12326Sgww@eng.sun.com 				flags++;
203*12326Sgww@eng.sun.com 				prefix ^= SUCCESS;
204*12326Sgww@eng.sun.com 			}
205*12326Sgww@eng.sun.com 		}
206*12326Sgww@eng.sun.com 
207*12326Sgww@eng.sun.com 		/* get class name */
208*12326Sgww@eng.sun.com 
209*12326Sgww@eng.sun.com 		for (i = 0; (i < sizeof (name) - 1) &&
210*12326Sgww@eng.sun.com 		    !(*flags == '\0' || *flags == ','); i++) {
211*12326Sgww@eng.sun.com 			name[i] = *flags++;
212*12326Sgww@eng.sun.com 		}
213*12326Sgww@eng.sun.com 		name[i++] = '\0';
214*12326Sgww@eng.sun.com 		if (*flags == ',') {
215*12326Sgww@eng.sun.com 			/* skip comma (',') */
216*12326Sgww@eng.sun.com 			flags++;
217*12326Sgww@eng.sun.com 		}
218*12326Sgww@eng.sun.com 		if (cacheauclassnam(&class, name) != 1) {
219*12326Sgww@eng.sun.com 			if (!cont) {
220*12326Sgww@eng.sun.com 				return (B_FALSE);
221*12326Sgww@eng.sun.com 			} else {
222*12326Sgww@eng.sun.com 				char	msg[512];
223*12326Sgww@eng.sun.com 
224*12326Sgww@eng.sun.com 				(void) snprintf(msg, sizeof (msg), "invalid "
225*12326Sgww@eng.sun.com 				    "audit flag %s", name);
226*12326Sgww@eng.sun.com 				adt_write_syslog(msg, EINVAL);
227*12326Sgww@eng.sun.com 			}
228*12326Sgww@eng.sun.com 		} else {
229*12326Sgww@eng.sun.com 			/* add class mask */
230*12326Sgww@eng.sun.com 
231*12326Sgww@eng.sun.com 			if ((prefix & (INVERSE | SUCCESS)) == SUCCESS) {
232*12326Sgww@eng.sun.com 				mask->am_success |= class->ac_class;
233*12326Sgww@eng.sun.com 			} else if ((prefix & (INVERSE | SUCCESS)) ==
234*12326Sgww@eng.sun.com 			    (INVERSE | SUCCESS)) {
235*12326Sgww@eng.sun.com 				mask->am_success &= ~(class->ac_class);
236*12326Sgww@eng.sun.com 			}
237*12326Sgww@eng.sun.com 			if ((prefix & (INVERSE | FAILURE)) == FAILURE) {
238*12326Sgww@eng.sun.com 				mask->am_failure |= class->ac_class;
239*12326Sgww@eng.sun.com 			} else if ((prefix & (INVERSE | FAILURE)) ==
240*12326Sgww@eng.sun.com 			    (INVERSE | FAILURE)) {
241*12326Sgww@eng.sun.com 				mask->am_failure &= ~(class->ac_class);
242*12326Sgww@eng.sun.com 			}
243*12326Sgww@eng.sun.com 		}
244*12326Sgww@eng.sun.com 	}
245*12326Sgww@eng.sun.com 
246*12326Sgww@eng.sun.com 	return (B_TRUE);
247*12326Sgww@eng.sun.com }
248*12326Sgww@eng.sun.com 
249*12326Sgww@eng.sun.com /*
2500Sstevel@tonic-gate  * getauditflagsbin() -  converts character string to success and
2510Sstevel@tonic-gate  *			 failure bit masks
2520Sstevel@tonic-gate  *
2530Sstevel@tonic-gate  * input:	auditstring - audit string
2540Sstevel@tonic-gate  *
2550Sstevel@tonic-gate  * output:	masks->am_success - audit on success
2560Sstevel@tonic-gate  *		masks->am_failure - audit on failure
2570Sstevel@tonic-gate  *
2580Sstevel@tonic-gate  * returns: 0 - ok
259*12326Sgww@eng.sun.com  *          -1 - error - string or mask NULL.
2600Sstevel@tonic-gate  */
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate int
getauditflagsbin(char * auditstring,au_mask_t * masks)263*12326Sgww@eng.sun.com getauditflagsbin(char *auditstring, au_mask_t *masks)
2640Sstevel@tonic-gate {
265*12326Sgww@eng.sun.com 	if (__chkflags(auditstring, masks, B_TRUE, NULL)) {
266*12326Sgww@eng.sun.com 		return (0);
267*12326Sgww@eng.sun.com 	}
268*12326Sgww@eng.sun.com 	return (-1);
2690Sstevel@tonic-gate }
270