Browse Source

Bug 244229 - targetattr not verified against schema when setting an aci

https://bugzilla.redhat.com/show_bug.cgi?id=244229

Description:
1. When acl contains targetattr keyword:
   (targetattr [!]= "attribute_1 || attribute_2 ...|| attribute_n"),
   where attribute_n does not contain '*', the current ACL plugin
   accepts any attribute_n value even if it is not defined in the
   schema.  This patch rejects the aci if it contains attribute_n
   not defined in schema with this error message:
   NSACLPlugin - targetattr "attribute_n" does not exist in schema.
   Please add attributeTypes "attribute_n" to schema if necessary.
   The message is logged in the error log as well as returned to
   the client.
2. To implement 1, slapi APIs slapi_attr_syntax_exists is added.
3. An attributeTypes "connection" is added to 01core389.ldif which
   is referred in an aci of cn=monitor.
Noriko Hosoi 15 years ago
parent
commit
0b7a84653e

+ 1 - 0
ldap/schema/01core389.ldif

@@ -124,6 +124,7 @@ attributeTypes: ( nsSSLPersonalitySSL-oid NAME 'nsSSLPersonalitySSL' DESC 'Netsc
 attributeTypes: ( nsSSLActivation-oid NAME 'nsSSLActivation' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape' )
 attributeTypes: ( 2.16.840.1.113730.3.1.2091 NAME 'nsslapd-suffix' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'Netscape' )
 attributeTypes: ( 2.16.840.1.113730.3.1.2092 NAME 'nsslapd-ldapiautodnsuffix' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'Netscape' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2095 NAME 'connection' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape' )
 #
 # objectclasses
 #

+ 1 - 1
ldap/servers/plugins/acl/acl.c

@@ -1482,7 +1482,7 @@ acl_check_mods(
 				if (strcmp(mod->mod_type, 
 					   aci_attr_type) == 0) {
 					if ( 0 != (rv = acl_verify_syntax( e_sdn,
-						      mod->mod_bvalues[i]))) {
+						                        mod->mod_bvalues[i], errbuf))) {
 						aclutil_print_err(rv, e_sdn, 
 							mod->mod_bvalues[i],
 							errbuf);

+ 2 - 2
ldap/servers/plugins/acl/acl.h

@@ -794,14 +794,14 @@ int 		acl_access_allowed_main ( Slapi_PBlock *pb, Slapi_Entry *e, char **attrs,
                           		  struct berval *val, int access , int flags, char **errbuf);
 int 		acl_access_allowed( Slapi_PBlock *pb, Slapi_Entry *e, char *attr,
 				        	struct berval *val, int access );
-int 		acl_verify_syntax(const Slapi_DN *e_sdn, const struct berval *bval);
+int 		acl_verify_syntax(const Slapi_DN *e_sdn, const struct berval *bval, char **errbuf);
 aclUserGroup * acl_get_usersGroup ( struct acl_pblock *aclpb , char *n_dn);
 void		acl_print_acllib_err (NSErr_t *errp , char * str);	
 int 		acl_check_mods( Slapi_PBlock *pb, Slapi_Entry *e, LDAPMod **mods, char **errbuf );
 int 		acl_verify_aci_syntax (Slapi_Entry *e, char **errbuf);
 char * 		acl__access2str(int access);
 void		acl_strcpy_special (char *d, char *s);
-int			acl_parse(char * str, aci_t *aci_item);
+int			acl_parse(char *str, aci_t *aci_item, char **errbuf);
 char *		acl_access2str ( int access );
 int 		acl_init_ext ();
 void * 		acl_get_ext (ext_type type, void *object);

+ 1 - 1
ldap/servers/plugins/acl/acllist.c

@@ -210,7 +210,7 @@ acllist_insert_aci_needsLock( const Slapi_DN *e_sdn, const struct berval* aci_at
 
 	acl_str = slapi_ch_strdup(aci_attr->bv_val);
 	/* Parse the ACL TEXT */
-	if (  0 != (rv = acl_parse ( acl_str, aci )) ) {
+	if (  0 != (rv = acl_parse ( acl_str, aci, NULL )) ) {
 		slapi_log_error (SLAPI_LOG_FATAL, plugin_name,
 				"ACL PARSE ERR(rv=%d): %s\n", rv, acl_str );
 		slapi_ch_free ( (void **) &acl_str );

+ 55 - 32
ldap/servers/plugins/acl/aclparse.c

@@ -45,14 +45,14 @@
 /****************************************************************************/
 /* prototypes                                                               */
 /****************************************************************************/
-static int		__aclp__parse_aci(char *str, aci_t  *aci_item);
-static int		__aclp__sanity_check_acltxt(aci_t *aci_item, char *str);
+static int __aclp__parse_aci(char *str, aci_t  *aci_item, char **errbuf);
+static int __aclp__sanity_check_acltxt(aci_t *aci_item, char *str);
 static char *	__aclp__normalize_acltxt (aci_t *aci_item, char *str);
 static char *	__aclp__getNextLASRule(aci_t *aci_item, char *str,
         								 char **endOfCurrRule);
 static int	__aclp__get_aci_right ( char *str);
-static int 	__aclp__init_targetattr (aci_t *aci, char *attr_val);
-static int			__acl__init_targetattrfilters( aci_t *aci_item, char *str);
+static int	__aclp__init_targetattr (aci_t *aci, char *attr_val, char **errbuf);
+static int	__acl__init_targetattrfilters( aci_t *aci_item, char *str);
 static int process_filter_list( Targetattrfilter ***attrfilterarray,
 								char * str);
 static int __acl_init_targetattrfilter( Targetattrfilter *attrfilter, char *str );
@@ -93,7 +93,7 @@ static int get_acl_rights_as_int( char * strValue);
 *
 **************************************************************************/
 int
-acl_parse(char * str, aci_t *aci_item)
+acl_parse(char * str, aci_t *aci_item, char **errbuf)
 {
 
 	int  		rv=0;
@@ -118,7 +118,7 @@ acl_parse(char * str, aci_t *aci_item)
 		*save = '\0';
 
 		/* Now we have a "str)" */
-		if ( 0 != (rv = __aclp__parse_aci(str, aci_item))) {
+		if ( 0 != (rv = __aclp__parse_aci(str, aci_item, errbuf))) {
 			return(rv);
 		}
 		
@@ -200,7 +200,7 @@ acl_parse(char * str, aci_t *aci_item)
 *
 **************************************************************************/
 static int
-__aclp__parse_aci (char 	*str, aci_t  *aci_item)
+__aclp__parse_aci(char *str, aci_t  *aci_item, char **errbuf)
 {
 
 	int		len;
@@ -242,8 +242,7 @@ __aclp__parse_aci (char 	*str, aci_t  *aci_item)
 			 *  (targetattrfilters="add= attr1:F1 && attr2:F2 ... && attrn:Fn,
 			 *                      del= attr1:F1 && attr2:F2... && attrn:Fn")
 			 */
-			if ( 0 != (rv= __acl__init_targetattrfilters(
-					aci_item, str))) {
+			if (0 != (rv = __acl__init_targetattrfilters(aci_item, str))) {
 				return  rv;
 			}
 		} else if (strncmp(str, aci_targetattr,targetattrlen ) == 0) {	
@@ -259,7 +258,7 @@ __aclp__parse_aci (char 	*str, aci_t  *aci_item)
 			 * If it contains a value filter, the type will also be
 			 *	ACI_TARGET_VALUE_ATTR.
 			 */
-			if (0 != (rv =  __aclp__init_targetattr(aci_item, str))) {
+			if (0 != (rv =  __aclp__init_targetattr(aci_item, str, errbuf))) {
 				return  rv;
 			}
 		} else if (strncmp(str, aci_targetfilter,tfilterlen ) == 0) {
@@ -1309,7 +1308,7 @@ acl_access2str(int access)
 *	
 ***************************************************************************/
 static int 
-__aclp__init_targetattr (aci_t *aci, char *attr_val)
+__aclp__init_targetattr (aci_t *aci, char *attr_val, char **errbuf)
 {
 
 	int		numattr=0;
@@ -1335,9 +1334,15 @@ __aclp__init_targetattr (aci_t *aci, char *attr_val)
 			s[len-1] = '\0'; /* trim trailing quote */
 		} else {
 			/* error - if it begins with a quote, it must end with a quote */
+			char *errstr = 
+					slapi_ch_smprintf("The statement does not begin and end "
+					                  "with a \": [%s]. ", attr_val);
 			slapi_log_error(SLAPI_LOG_FATAL, plugin_name,
-							"__aclp__init_targetattr: Error: The statement does not begin and end with a \": [%s]\n",
-							attr_val);
+							"__aclp__init_targetattr: %s\n", errstr);
+			if (errbuf) {
+				aclutil_str_append(errbuf, errstr);
+			}
+			slapi_ch_free_string(&errstr);
 			return ACL_SYNTAX_ERR;
 		}
 		s++; /* skip leading quote */
@@ -1372,16 +1377,14 @@ __aclp__init_targetattr (aci_t *aci, char *attr_val)
 		 * Here:
 		 * end_attr points to the next attribute thing.
 		 *
-	  	 * str points to the current one to be processed and it looks like this:
+		 * str points to the current one to be processed and it looks like this:
 		 * rbyrneXXX Watchout is it OK to use : as the speperator ?
 		 * cn
 		 * c*n*
-         * *
+		 * *
+		 *
 		 * The attribute goes in the attrTarget list.
-		 * 
-		*/
-
-
+		 */
 		attr = (Targetattr *) slapi_ch_malloc (sizeof (Targetattr));
 		memset (attr, 0, sizeof(Targetattr));
                                 
@@ -1392,7 +1395,6 @@ __aclp__init_targetattr (aci_t *aci, char *attr_val)
 			str++;
 		}
 		if (strchr(str, '*')) {
-             		
 			/* It contains a * so it's something like * or cn* */
 			if (strcmp(str, "*" ) != 0) {
 				char			line[100];
@@ -1410,29 +1412,50 @@ __aclp__init_targetattr (aci_t *aci, char *attr_val)
 				f = slapi_str2filter (lineptr);
 	
 				if (f == NULL)  {
-                   	slapi_log_error(SLAPI_LOG_FATAL, plugin_name,
-					  "__aclp__init_targetattr:Unable to generate filter (%s)\n", lineptr);
+					char *errstr = slapi_ch_smprintf("Unable to generate filter"
+					                                 " (%s). ", lineptr);
+					slapi_log_error(SLAPI_LOG_FATAL, plugin_name,
+							"__aclp__init_targetattr: %s\n", errstr);
+					if (errbuf) {
+						aclutil_str_append(errbuf, errstr);
+					}
+					slapi_ch_free_string(&errstr);
 				} else {
 					attr->u.attr_filter = f;
 				}
 
-				if (newline) slapi_ch_free((void **) &newline);
+				slapi_ch_free_string(&newline);
 			} else {
 				attr->attr_type = ACL_ATTR_STAR;
 				attr->u.attr_str = slapi_ch_strdup (str);
 			}
 
 		} else {
-			attr->u.attr_str = slapi_ch_strdup (str);				
-            attr->attr_type = ACL_ATTR_STRING;
+			/* targetattr = str or targetattr != str */
+			/* Make sure str is a valid attribute */
+			if (slapi_attr_syntax_exists((const char *)str)) {
+				attr->u.attr_str = slapi_ch_strdup (str);
+				attr->attr_type = ACL_ATTR_STRING;
+			} else {
+				char *errstr = slapi_ch_smprintf("targetattr \"%s\" does not "
+				                  "exist in schema. Please add attributeTypes "
+				                  "\"%s\" to schema if necessary. ", str, str);
+				slapi_log_error(SLAPI_LOG_FATAL, plugin_name,
+				                "__aclp__init_targetattr: %s\n", errstr);
+				if (errbuf) {
+					aclutil_str_append(errbuf, errstr);
+				}
+				slapi_ch_free_string(&errstr);
+				slapi_ch_free((void **)&attr);
+				return ACL_SYNTAX_ERR;
+			}
 		}
 
-
 		/*
 		 * Add the attr to the targetAttr list
-		*/
+		 */
 
-     	attrArray[numattr] = attr;
+		attrArray[numattr] = attr;
 		numattr++;
 		if (!(numattr % ACL_INIT_ATTR_ARRAY)) {
 			aci->targetAttr = (Targetattr **) slapi_ch_realloc (
@@ -1441,7 +1464,6 @@ __aclp__init_targetattr (aci_t *aci, char *attr_val)
 						     sizeof(Targetattr *));
             				attrArray = aci->targetAttr;
 		}
-	
 
 		/* Move on to the next attribute in the list */
 		str = end_attr;
@@ -1512,7 +1534,7 @@ acl_verify_aci_syntax (Slapi_Entry *e, char **errbuf)
 		i= slapi_attr_first_value ( attr,&sval );
 		while ( i != -1 ) {
 		        attrVal = slapi_value_get_berval ( sval );
-		        rv=acl_verify_syntax ( e_sdn, attrVal);
+		        rv = acl_verify_syntax( e_sdn, attrVal, errbuf );
 			if ( 0 != rv ) {
 				aclutil_print_err(rv, e_sdn, attrVal, errbuf);
 				return ACL_ERR;
@@ -1540,7 +1562,8 @@ acl_verify_aci_syntax (Slapi_Entry *e, char **errbuf)
 *
 **************************************************************************/
 int
-acl_verify_syntax(const Slapi_DN *e_sdn, const struct berval *bval)
+acl_verify_syntax(const Slapi_DN *e_sdn, 
+                  const struct berval *bval, char **errbuf)
 {
 	aci_t			*aci_item;
 	int				rv = 0;
@@ -1550,7 +1573,7 @@ acl_verify_syntax(const Slapi_DN *e_sdn, const struct berval *bval)
 
 	/* make a copy the the string */
 	str =  slapi_ch_strdup(bval->bv_val);
-	rv = acl_parse(str, aci_item);
+	rv = acl_parse(str, aci_item, errbuf);
 
 	/* cleanup before you leave ... */
 	acllist_free_aci (aci_item);

+ 6 - 0
ldap/servers/slapd/attrsyntax.c

@@ -1072,3 +1072,9 @@ attr_syntax_init(void)
 	}
 	return 0;
 }
+
+int
+slapi_attr_syntax_exists(const char *attr_name)
+{
+    return attr_syntax_exists(attr_name);
+}

+ 8 - 0
ldap/servers/slapd/slapi-plugin.h

@@ -4480,6 +4480,14 @@ int slapi_filter_compare(struct slapi_filter *f1, struct slapi_filter *f2);
 Slapi_Filter *slapi_filter_dup(Slapi_Filter *f);
 int slapi_filter_changetype(Slapi_Filter *f, const char *newtype);
 
+/**
+ * Check whether a given attribute type is defined in schema or not
+ *
+ * \param attribute type name to be checked
+ * \return \c 0 if the attribute type is not defined in schema
+ * \return non-0 if the attribute type is defined in schema
+ */
+int slapi_attr_syntax_exists(const char *type);
 
 /*
  * slapi_filter_apply() is used to apply a function to each simple filter