xref: /titanic_52/usr/src/lib/libbsm/common/getauditflags.c (revision f8804e7f3998d21c6669eec957c51b0ed836bbb9)
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
5*f8804e7fSgww  * Common Development and Distribution License (the "License").
6*f8804e7fSgww  * 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 /*
22*f8804e7fSgww  * 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 
29*f8804e7fSgww #include <ctype.h>
307c478bd9Sstevel@tonic-gate #include <stdio.h>
317c478bd9Sstevel@tonic-gate #include <string.h>
32*f8804e7fSgww 
33*f8804e7fSgww #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 
38*f8804e7fSgww #include <adt_xlate.h>		/* adt_write_syslog */
397c478bd9Sstevel@tonic-gate 
40*f8804e7fSgww #define	SUCCESS 0x1		/* '+' success mask */
41*f8804e7fSgww #define	FAILURE	0x2		/* '-' failure mask */
42*f8804e7fSgww #define	INVERSE	0x4		/* '^' invert the mask */
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate static int
45*f8804e7fSgww 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) {
51*f8804e7fSgww 		if (v == 0) {
52*f8804e7fSgww 			(void) strncat(s, p_class->ac_name, AU_CLASS_NAME_MAX);
53*f8804e7fSgww 		} else {
54*f8804e7fSgww 			(void) strncat(s, p_class->ac_desc, AU_CLASS_DESC_MAX);
55*f8804e7fSgww 		}
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
76*f8804e7fSgww 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;
93*f8804e7fSgww 		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 = "-";
1207c478bd9Sstevel@tonic-gate 		else
1217c478bd9Sstevel@tonic-gate 			continue;
1227c478bd9Sstevel@tonic-gate 		if (match_class(auditstring, prefix, m, verbose) != 0)
1237c478bd9Sstevel@tonic-gate 			return (-1);
1247c478bd9Sstevel@tonic-gate 	}
125*f8804e7fSgww 	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 /*
132*f8804e7fSgww  *  Audit flags:
133*f8804e7fSgww  *
134*f8804e7fSgww  *	[+ | - | ^ | ^+ | ^-]<classname>{,[+ | - | ^ | ^+ | ^-]<classname>}*
135*f8804e7fSgww  *
136*f8804e7fSgww  *	  <classname>, add class mask to success and failure mask.
137*f8804e7fSgww  *	 +<classname>, add class mask only to success mask.
138*f8804e7fSgww  *	 -<classname>, add class mask only to failure mask.
139*f8804e7fSgww  *	 ^<classname>, remove class mask from success and failure mask.
140*f8804e7fSgww  *	^+<classname>, remove class mask from success mask.
141*f8804e7fSgww  *	^-<classname>, remove class mask from failure mask.
142*f8804e7fSgww  */
143*f8804e7fSgww 
144*f8804e7fSgww /*
145*f8804e7fSgww  * __chkflags - check if the audit flags are valid for this system
146*f8804e7fSgww  *
147*f8804e7fSgww  *	Entry	flags = audit flags string.
148*f8804e7fSgww  *		cont  = B_TRUE, continue parsing even if error.
149*f8804e7fSgww  *			B_FALSE, return failure on error.
150*f8804e7fSgww  *
151*f8804e7fSgww  *	Exit	mask = audit mask as defined by flags.
152*f8804e7fSgww  *
153*f8804e7fSgww  *	Return	B_TRUE if no errors, or continue == B_TRUE.
154*f8804e7fSgww  *		B_FALSE and if error != NULL, flags in error.
155*f8804e7fSgww  */
156*f8804e7fSgww 
157*f8804e7fSgww boolean_t
158*f8804e7fSgww __chkflags(char *flags, au_mask_t *mask, boolean_t cont, char **error)
159*f8804e7fSgww {
160*f8804e7fSgww 	uint32_t	prefix;
161*f8804e7fSgww 	au_class_ent_t	*class;
162*f8804e7fSgww 	char		name[AU_CLASS_NAME_MAX+1];
163*f8804e7fSgww 	int		i;
164*f8804e7fSgww 
165*f8804e7fSgww 	if (flags == NULL || mask == NULL) {
166*f8804e7fSgww 		return (B_FALSE);
167*f8804e7fSgww 	}
168*f8804e7fSgww 
169*f8804e7fSgww 	mask->am_success = 0;
170*f8804e7fSgww 	mask->am_failure = 0;
171*f8804e7fSgww 
172*f8804e7fSgww 	while (*flags != '\0') {
173*f8804e7fSgww 		prefix = (SUCCESS | FAILURE);
174*f8804e7fSgww 
175*f8804e7fSgww 		/* skip white space */
176*f8804e7fSgww 		while (isspace(*flags)) {
177*f8804e7fSgww 			flags++;
178*f8804e7fSgww 		}
179*f8804e7fSgww 
180*f8804e7fSgww 		if (flags == '\0') {
181*f8804e7fSgww 			break;
182*f8804e7fSgww 		}
183*f8804e7fSgww 		if (error != NULL) {
184*f8804e7fSgww 			/* save error pointer */
185*f8804e7fSgww 			*error = flags;
186*f8804e7fSgww 		}
187*f8804e7fSgww 
188*f8804e7fSgww 		/* get the prefix */
189*f8804e7fSgww 		if (*flags == '+') {
190*f8804e7fSgww 			flags++;
191*f8804e7fSgww 			prefix ^= FAILURE;
192*f8804e7fSgww 		} else if (*flags == '-') {
193*f8804e7fSgww 			flags++;
194*f8804e7fSgww 			prefix ^= SUCCESS;
195*f8804e7fSgww 		} else if (*flags == '^') {
196*f8804e7fSgww 			flags++;
197*f8804e7fSgww 			prefix |= INVERSE;
198*f8804e7fSgww 			if (*flags == '+') {
199*f8804e7fSgww 				flags++;
200*f8804e7fSgww 				prefix ^= FAILURE;
201*f8804e7fSgww 			} else if (*flags == '-') {
202*f8804e7fSgww 				flags++;
203*f8804e7fSgww 				prefix ^= SUCCESS;
204*f8804e7fSgww 			}
205*f8804e7fSgww 		}
206*f8804e7fSgww 
207*f8804e7fSgww 		/* get class name */
208*f8804e7fSgww 
209*f8804e7fSgww 		for (i = 0; (i < sizeof (name) - 1) &&
210*f8804e7fSgww 		    !(*flags == '\0' || *flags == ','); i++) {
211*f8804e7fSgww 			name[i] = *flags++;
212*f8804e7fSgww 		}
213*f8804e7fSgww 		name[i++] = '\0';
214*f8804e7fSgww 		if (*flags == ',') {
215*f8804e7fSgww 			/* skip comma (',') */
216*f8804e7fSgww 			flags++;
217*f8804e7fSgww 		}
218*f8804e7fSgww 		if (cacheauclassnam(&class, name) != 1) {
219*f8804e7fSgww 			if (!cont) {
220*f8804e7fSgww 				return (B_FALSE);
221*f8804e7fSgww 			} else {
222*f8804e7fSgww 				char	msg[512];
223*f8804e7fSgww 
224*f8804e7fSgww 				(void) snprintf(msg, sizeof (msg), "invalid "
225*f8804e7fSgww 				    "audit flag %s", name);
226*f8804e7fSgww 				adt_write_syslog(msg, EINVAL);
227*f8804e7fSgww 			}
228*f8804e7fSgww 		} else {
229*f8804e7fSgww 			/* add class mask */
230*f8804e7fSgww 
231*f8804e7fSgww 			if ((prefix & (INVERSE | SUCCESS)) == SUCCESS) {
232*f8804e7fSgww 				mask->am_success |= class->ac_class;
233*f8804e7fSgww 			} else if ((prefix & (INVERSE | SUCCESS)) ==
234*f8804e7fSgww 			    (INVERSE | SUCCESS)) {
235*f8804e7fSgww 				mask->am_success &= ~(class->ac_class);
236*f8804e7fSgww 			}
237*f8804e7fSgww 			if ((prefix & (INVERSE | FAILURE)) == FAILURE) {
238*f8804e7fSgww 				mask->am_failure |= class->ac_class;
239*f8804e7fSgww 			} else if ((prefix & (INVERSE | FAILURE)) ==
240*f8804e7fSgww 			    (INVERSE | FAILURE)) {
241*f8804e7fSgww 				mask->am_failure &= ~(class->ac_class);
242*f8804e7fSgww 			}
243*f8804e7fSgww 		}
244*f8804e7fSgww 	}
245*f8804e7fSgww 
246*f8804e7fSgww 	return (B_TRUE);
247*f8804e7fSgww }
248*f8804e7fSgww 
249*f8804e7fSgww /*
2507c478bd9Sstevel@tonic-gate  * getauditflagsbin() -  converts character string to success and
2517c478bd9Sstevel@tonic-gate  *			 failure bit masks
2527c478bd9Sstevel@tonic-gate  *
2537c478bd9Sstevel@tonic-gate  * input:	auditstring - audit string
2547c478bd9Sstevel@tonic-gate  *
2557c478bd9Sstevel@tonic-gate  * output:	masks->am_success - audit on success
2567c478bd9Sstevel@tonic-gate  *		masks->am_failure - audit on failure
2577c478bd9Sstevel@tonic-gate  *
2587c478bd9Sstevel@tonic-gate  * returns: 0 - ok
259*f8804e7fSgww  *          -1 - error - string or mask NULL.
2607c478bd9Sstevel@tonic-gate  */
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate int
263*f8804e7fSgww getauditflagsbin(char *auditstring, au_mask_t *masks)
2647c478bd9Sstevel@tonic-gate {
265*f8804e7fSgww 	if (__chkflags(auditstring, masks, B_TRUE, NULL)) {
266*f8804e7fSgww 		return (0);
267*f8804e7fSgww 	}
2687c478bd9Sstevel@tonic-gate 	return (-1);
2697c478bd9Sstevel@tonic-gate }
270