changeset 12326:7a0184667fca

6946518 There is no way to validate that audit flags are valid 6946529 getauditflagschar and getauclassnam may not operate properly with maximum size class names 6927607 getauditflags.c:getauditflagsbin() needs boundary checking.
author gww <gww@eng.sun.com>
date Thu, 06 May 2010 16:36:08 -0700
parents 8a132ae95aa2
children 4256c66fb5bf
files usr/src/lib/libbsm/common/audit_class.c usr/src/lib/libbsm/common/getauditflags.c usr/src/lib/libbsm/common/libbsm.h usr/src/lib/libbsm/common/mapfile-vers
diffstat 4 files changed, 153 insertions(+), 147 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/libbsm/common/audit_class.c	Thu May 06 19:01:43 2010 -0400
+++ b/usr/src/lib/libbsm/common/audit_class.c	Thu May 06 16:36:08 2010 -0700
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -183,7 +182,7 @@
 getauclassnam_r(au_class_ent_t *e, char *name)
 {
 	while (getauclassent_r(e) != NULL) {
-		if (strcmp(e->ac_name, name) == 0) {
+		if (strncmp(e->ac_name, name, AU_CLASS_NAME_MAX) == 0) {
 			return (e);
 		}
 	}
@@ -287,7 +286,8 @@
 	*result = class_tbl[invalid];
 	if (flags & AU_CACHE_NAME) {
 		for (i = 0; i < lines; i++) {
-			if (strcmp(class_name, class_tbl[i]->ac_name) == 0) {
+			if (strncmp(class_name, class_tbl[i]->ac_name,
+			    AU_CLASS_NAME_MAX) == 0) {
 				*result = class_tbl[i];
 				hit = 1;
 				break;
--- a/usr/src/lib/libbsm/common/getauditflags.c	Thu May 06 19:01:43 2010 -0400
+++ b/usr/src/lib/libbsm/common/getauditflags.c	Thu May 06 16:36:08 2010 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,50 +19,46 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
  */
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 /*
  * get audit preselection mask values
  */
 
+#include <ctype.h>
 #include <stdio.h>
 #include <string.h>
-#include <syslog.h>
+
+#include <sys/errno.h>
 #include <sys/types.h>
 #include <bsm/audit.h>
 #include <bsm/libbsm.h>
 
-#define	ON 1
-#define	OK 0
-#define	OFF -1
-#define	COMMA  ','
+#include <adt_xlate.h>		/* adt_write_syslog */
 
-#define	MAXFLDLEN 25
-
-int getauditflagsbin();
+#define	SUCCESS 0x1		/* '+' success mask */
+#define	FAILURE	0x2		/* '-' failure mask */
+#define	INVERSE	0x4		/* '^' invert the mask */
 
 static int
-match_class(s, prefix, m, v)
-char	*s;
-char	*prefix;
-unsigned int	m;
-int	v;
+match_class(char *s, char *prefix, uint_t m, int v)
 {
 	au_class_ent_t *p_class;
 
 	(void) strcat(s, prefix);
 	if (cacheauclass(&p_class, m) == 1) {
-		(void) strcat(s, v ? p_class->ac_desc : p_class->ac_name);
+		if (v == 0) {
+			(void) strncat(s, p_class->ac_name, AU_CLASS_NAME_MAX);
+		} else {
+			(void) strncat(s, p_class->ac_desc, AU_CLASS_DESC_MAX);
+		}
 		(void) strcat(s, ",");
 		return (0);
 	}
 	return (-1);
 }
 
-
 /*
  * getauditflagschar() - convert bit flag to character string
  *
@@ -78,10 +73,7 @@
  */
 
 int
-getauditflagschar(auditstring, masks, verbose)
-char	*auditstring;
-au_mask_t *masks;
-int	verbose;
+getauditflagschar(char *auditstring, au_mask_t *masks, int verbose)
 {
 	char	*prefix;		/* +, -, or null */
 	unsigned int	m;		/* for masking with masks */
@@ -98,7 +90,7 @@
 			return (-1);
 		/* kludge to get rid of trailing comma */
 		l = strlen(auditstring) - 1;
-		if (auditstring[l] == COMMA)
+		if (auditstring[l] == ',')
 			auditstring[l] = '\0';
 		return (0);
 	}
@@ -125,140 +117,153 @@
 			prefix = "+";
 		else if (m & masks->am_failure)
 			prefix = "-";
-			else
+		else
 			continue;
 		if (match_class(auditstring, prefix, m, verbose) != 0)
 			return (-1);
 	}
-	if (*(prefix = auditstring + strlen(auditstring) - 1) == COMMA)
+	if (*(prefix = auditstring + strlen(auditstring) - 1) == ',')
 		*prefix = '\0';
 	return (0);
 
 }
 
 /*
+ *  Audit flags:
+ *
+ *	[+ | - | ^ | ^+ | ^-]<classname>{,[+ | - | ^ | ^+ | ^-]<classname>}*
+ *
+ *	  <classname>, add class mask to success and failure mask.
+ *	 +<classname>, add class mask only to success mask.
+ *	 -<classname>, add class mask only to failure mask.
+ *	 ^<classname>, remove class mask from success and failure mask.
+ *	^+<classname>, remove class mask from success mask.
+ *	^-<classname>, remove class mask from failure mask.
+ */
+
+/*
+ * __chkflags - check if the audit flags are valid for this system
+ *
+ *	Entry	flags = audit flags string.
+ *		cont  = B_TRUE, continue parsing even if error.
+ *			B_FALSE, return failure on error.
+ *
+ *	Exit	mask = audit mask as defined by flags.
+ *
+ *	Return	B_TRUE if no errors, or continue == B_TRUE.
+ *		B_FALSE and if error != NULL, flags in error.
+ */
+
+boolean_t
+__chkflags(char *flags, au_mask_t *mask, boolean_t cont, char **error)
+{
+	uint32_t	prefix;
+	au_class_ent_t	*class;
+	char		name[AU_CLASS_NAME_MAX+1];
+	int		i;
+
+	if (flags == NULL || mask == NULL) {
+		return (B_FALSE);
+	}
+
+	mask->am_success = 0;
+	mask->am_failure = 0;
+
+	while (*flags != '\0') {
+		prefix = (SUCCESS | FAILURE);
+
+		/* skip white space */
+		while (isspace(*flags)) {
+			flags++;
+		}
+
+		if (flags == '\0') {
+			break;
+		}
+		if (error != NULL) {
+			/* save error pointer */
+			*error = flags;
+		}
+
+		/* get the prefix */
+		if (*flags == '+') {
+			flags++;
+			prefix ^= FAILURE;
+		} else if (*flags == '-') {
+			flags++;
+			prefix ^= SUCCESS;
+		} else if (*flags == '^') {
+			flags++;
+			prefix |= INVERSE;
+			if (*flags == '+') {
+				flags++;
+				prefix ^= FAILURE;
+			} else if (*flags == '-') {
+				flags++;
+				prefix ^= SUCCESS;
+			}
+		}
+
+		/* get class name */
+
+		for (i = 0; (i < sizeof (name) - 1) &&
+		    !(*flags == '\0' || *flags == ','); i++) {
+			name[i] = *flags++;
+		}
+		name[i++] = '\0';
+		if (*flags == ',') {
+			/* skip comma (',') */
+			flags++;
+		}
+		if (cacheauclassnam(&class, name) != 1) {
+			if (!cont) {
+				return (B_FALSE);
+			} else {
+				char	msg[512];
+
+				(void) snprintf(msg, sizeof (msg), "invalid "
+				    "audit flag %s", name);
+				adt_write_syslog(msg, EINVAL);
+			}
+		} else {
+			/* add class mask */
+
+			if ((prefix & (INVERSE | SUCCESS)) == SUCCESS) {
+				mask->am_success |= class->ac_class;
+			} else if ((prefix & (INVERSE | SUCCESS)) ==
+			    (INVERSE | SUCCESS)) {
+				mask->am_success &= ~(class->ac_class);
+			}
+			if ((prefix & (INVERSE | FAILURE)) == FAILURE) {
+				mask->am_failure |= class->ac_class;
+			} else if ((prefix & (INVERSE | FAILURE)) ==
+			    (INVERSE | FAILURE)) {
+				mask->am_failure &= ~(class->ac_class);
+			}
+		}
+	}
+
+	return (B_TRUE);
+}
+
+/*
  * getauditflagsbin() -  converts character string to success and
  *			 failure bit masks
  *
  * input:	auditstring - audit string
- *		cnt - number of elements in the masks array
  *
  * output:	masks->am_success - audit on success
  *		masks->am_failure - audit on failure
  *
  * returns: 0 - ok
- *	    -1 - error - string contains characters which do
- *		not match event flag names or invalid pointers
- *              passed in.
+ *          -1 - error - string or mask NULL.
  */
 
 int
-getauditflagsbin(auditstring, masks)
-char	*auditstring;
-au_mask_t *masks;
+getauditflagsbin(char *auditstring, au_mask_t *masks)
 {
-	int	gotone, done = 0, invert = 0, tryagain;
-	int	retstat = 0, succ_event, fail_event;
-	char	*ptr, tmp_buff[MAXFLDLEN];
-	au_class_ent_t *p_class;
-
-	if ((masks == NULL) || (auditstring == NULL))
-		return (-1);
-
-	masks->am_success = masks->am_failure = 0;
-
-	/* process character string */
-	do {
-		gotone = 0;
-		/* read through string storing chars. until a comma */
-		for (ptr = tmp_buff; !gotone; /* */) {
-			if (*auditstring != COMMA && *auditstring != '\0' &&
-			    *auditstring != '\n' && *auditstring != ' ' &&
-			    *auditstring != '\t')
-				*ptr++ = *auditstring++;
-			else if (*auditstring == ' ' || *auditstring == '\t')
-				auditstring++;
-			else {
-				if (*auditstring == '\0' ||
-						*auditstring == '\n') {
-					done = 1;
-					if (ptr == tmp_buff)
-						done = 2;
-				}
-				gotone = 1;
-			}
-		}
-		/* * process audit state */
-		if (gotone && done != 2) {
-			if (!done)
-				auditstring++;
-			*ptr++ = '\0';
-			ptr = tmp_buff;
-			gotone = 0;
-			succ_event = ON;
-			fail_event = ON;
-			tryagain = 1;
-			invert = 0;
-
-			/* get flags */
-			do {
-				switch (*ptr++) {
-				case '^':
-					invert = 1;
-					succ_event = OFF;
-					fail_event = OFF;
-					break;
-				case '+':
-					if (invert)
-						fail_event = OK;
-					else {
-						succ_event = ON;
-						fail_event = OK;
-					}
-					break;
-				case '-':
-					if (invert)
-						succ_event = OK;
-					else {
-						fail_event = ON;
-						succ_event = OK;
-					}
-					break;
-				default:
-					tryagain = 0;
-					ptr--;
-					break;
-				}
-			} while (tryagain);
-
-			/* add audit state to mask */
-
-
-			if (cacheauclassnam(&p_class, ptr) == 1) {
-				if (succ_event == ON)
-					masks->am_success |= p_class->ac_class;
-				else if (succ_event == OFF)
-					masks->am_success &=
-						~(p_class->ac_class);
-				if (fail_event == ON)
-					masks->am_failure |= p_class->ac_class;
-				else if (fail_event == OFF)
-					masks->am_failure &=
-						~(p_class->ac_class);
-				gotone = 1;
-			} else {  /* Bug 4330887 */
-				syslog(LOG_CRIT,
-					"auditflags have invalid flag %s",
-					ptr);
-				continue;
-			}
-			if (!gotone) {
-				retstat = -1;
-				done = 1;
-			}
-		}
-	} while (!done);
-
-
-	return (retstat);
+	if (__chkflags(auditstring, masks, B_TRUE, NULL)) {
+		return (0);
+	}
+	return (-1);
 }
--- a/usr/src/lib/libbsm/common/libbsm.h	Thu May 06 19:01:43 2010 -0400
+++ b/usr/src/lib/libbsm/common/libbsm.h	Thu May 06 16:36:08 2010 -0700
@@ -19,14 +19,14 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #ifndef _BSM_LIBBSM_H
 #define	_BSM_LIBBSM_H
 
 
+#include <ctype.h>
 #include <secdb.h>
 #include <stdio.h>
 #include <errno.h>
@@ -223,6 +223,7 @@
 extern int	getauditflagsbin(char *, au_mask_t *);
 extern int	getauditflagschar(char *, au_mask_t *, int);
 extern int	getfauditflags(au_mask_t *, au_mask_t *, au_mask_t *);
+extern boolean_t __chkflags(char *, au_mask_t *, boolean_t, char **);
 
 /*
  * Functions that do system calls
--- a/usr/src/lib/libbsm/common/mapfile-vers	Thu May 06 19:01:43 2010 -0400
+++ b/usr/src/lib/libbsm/common/mapfile-vers	Thu May 06 16:36:08 2010 -0700
@@ -19,8 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
 #
 
 #
@@ -291,6 +290,7 @@
 	cacheauclassnam;
 	cacheauevent;
 	cannot_audit;
+	__chkflags;
 	da_add_list;
 	da_check_logindevperm;
 	da_is_on;