[Fedora-directory-commits] ldapserver/ldap/servers/plugins/acl acleffectiverights.c, 1.7, 1.8

Noriko Hosoi (nhosoi) fedora-directory-commits at redhat.com
Fri Jun 27 19:28:24 UTC 2008


Author: nhosoi

Update of /cvs/dirsec/ldapserver/ldap/servers/plugins/acl
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv6584/ldap/servers/plugins/acl

Modified Files:
	acleffectiverights.c 
Log Message:
Resolves: #437525
Summary: GER: allow GER for non-existing entries
Description:
[slapd/charray.c]
new: charray_merge_nodup -- merge 2 string arrays skipping the duplicates
modified: charray_remove -- introduced "freeit" flag.  If true, the removed
string is freed.  (The API is used only in chainingdb.	The change is applied
to the plugin.)

[slapd/opshared.c]
modified: check OP_FLAG_GET_EFFECTIVE_RIGHTS in the iterate to support
"@<objectclass>".  It's needed to do at the location since we have to call acl
plugin even
when no entries are returned from the search.  If no entries are returned and
"@<objectclass>" is found in the attribute list, acl effective rights code
generates the corresponding template entry.

[slapd/pblock.c]
place to store gerattrs is added (SLAPI_SEARCH_GERATTRS), where gerattrs is an
array of strings which store "...@<objectclass>".

[slapd/result.c]
moved OP_FLAG_GET_EFFECTIVE_RIGHTS checking to iterate (opshared.c)

[slapd/schema.c]
new: slapi_schema_list_objectclass_attributes -- return the required and/or
allowed attributes belonging to the given objectclass.	This is used to support
"*" and "+" in the get effective rights.
new: slapi_schema_get_superior_name -- return the superior objectclass name of
the given objectclass.

[slapd/search.c]
if "<attr>@<objectclass>" is found in the attribute list, cut the <attr> part
out and added to the attrs array (pblock SLAPI_SEARCH_ATTRS) and store the
original
string to the gerattrs (pblock SLAPI_SEARCH_GERATTRS).

[plugin/acl/acleffectiverights.c]
modified: _ger_g_permission_granted -- if the requester and the subject user
are
identical, give "g" permission
modified: _ger_parse_control -- replaced strcpy with memmove since strcpy does
not guarantee the result of the overlap copy.
modified: _ger_get_attrs_rights -- support "*" (all attributes belonging to the
object) and "+" (operational attributes).  If repeated attributes are found in
the given attribute list, they are reduced to one.
new: _ger_generate_template_entry -- generate a template entry if
"@<objectclass>" is passed.

[pluginc/cb/*]
adjusted to the updated charray_remove.

Please see also this wiki page for the overview and test cases.
http://directory.fedoraproject.org/wiki/Get_Effective_Rights_for_non-present_attributes



Index: acleffectiverights.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/plugins/acl/acleffectiverights.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- acleffectiverights.c	18 Oct 2007 00:08:27 -0000	1.7
+++ acleffectiverights.c	27 Jun 2008 19:28:22 -0000	1.8
@@ -46,7 +46,13 @@
 /* news2 is optional, provided as a convenience */
 /* capacity is the capacity of the gerstr, size is the current length */
 static void
-_append_gerstr(char **gerstr, size_t *capacity, size_t *size, const char *news, const char *news2)
+_append_gerstr(
+	char **gerstr,
+	size_t *capacity,
+	size_t *size,
+	const char *news,
+	const char *news2
+	)
 {
 	size_t len;
 	size_t increment = 128;
@@ -90,7 +96,12 @@
 }
 
 static int
-_ger_g_permission_granted ( Slapi_PBlock *pb, Slapi_Entry *e, char **errbuf )
+_ger_g_permission_granted (
+	Slapi_PBlock *pb,
+	Slapi_Entry *e,
+	const char *subjectdn,
+	char **errbuf
+	)
 {
 	char *proxydn = NULL;
 	Slapi_DN *requestor_sdn, *entry_sdn;
@@ -151,6 +162,14 @@
 		goto bailout;
 	}
 
+	/* if the requestor and the subject user are identical, let's grant it */
+	if ( strcasecmp ( slapi_sdn_get_ndn(requestor_sdn), subjectdn ) == 0)
+	{
+		/* Requestor should see his own permission rights on any entry */
+		rc = LDAP_SUCCESS;
+		goto bailout;
+	}
+
 	aclutil_str_appened ( errbuf, "get-effective-rights: requestor has no g permission on the entry" );
 	slapi_log_error (SLAPI_LOG_ACL, plugin_name,
 				"_ger_g_permission_granted: %s\n", *errbuf);
@@ -166,11 +185,17 @@
 }
 
 static int
-_ger_parse_control ( Slapi_PBlock *pb, char **subjectndn, int *iscritical, char **errbuf )
+_ger_parse_control (
+	Slapi_PBlock *pb,
+	char **subjectndn,
+	int *iscritical,
+	char **errbuf
+	)
 {
 	LDAPControl **requestcontrols;
 	struct berval *subjectber;
 	BerElement *ber;
+	int subjectndnlen = 0;
 
 	if (NULL == subjectndn)
 	{
@@ -231,7 +256,8 @@
 	 * (see section 9 of RFC 2829) only. It also only supports the "dnAuthzId"
 	 * flavor, which looks like "dn:<DN>" where null <DN> is for anonymous.
 	 */
-	if ( NULL == *subjectndn || strlen (*subjectndn) < 3 ||
+	subjectndnlen = strlen(*subjectndn);
+	if ( NULL == *subjectndn || subjectndnlen < 3 ||
 		 strncasecmp ( "dn:", *subjectndn, 3 ) != 0 )
 	{
 		aclutil_str_appened ( errbuf, "get-effective-rights: subject is not dnAuthzId" );
@@ -239,7 +265,8 @@
 		return LDAP_INVALID_SYNTAX;
 	}
 
-	strcpy ( *subjectndn, *subjectndn + 3 );
+	/* memmove is safe for overlapping copy */
+	memmove ( *subjectndn, *subjectndn + 3, subjectndnlen - 2);/* 1 for '\0' */
 	slapi_dn_normalize ( *subjectndn );
 	return LDAP_SUCCESS;
 }
@@ -533,6 +560,27 @@
 	return attrrights;
 }
 
+#define GER_GET_ATTR_RIGHTS(attrs) \
+	for (thisattr = (attrs); thisattr && *thisattr; thisattr++) \
+	{ \
+		_ger_get_attr_rights (gerpb, e, subjectndn, *thisattr, \
+						gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf); \
+		isfirstattr = 0; \
+	} \
+
+#define GER_GET_ATTR_RIGHTA_EXT(c, inattrs, exattrs); \
+	for ( i = 0; attrs[i]; i++ ) \
+	{ \
+		if ((c) != *attrs[i] && charray_inlist((inattrs), attrs[i]) && \
+				!charray_inlist((exattrs), attrs[i])) \
+		{ \
+			_ger_get_attr_rights ( gerpb, e, subjectndn, attrs[i], \
+				gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf ); \
+			isfirstattr = 0; \
+		} \
+	}
+
+
 void
 _ger_get_attrs_rights (
 	Slapi_PBlock *gerpb,
@@ -552,12 +600,76 @@
 
 	if (attrs && *attrs)
 	{
-		int i;
-		for ( i = 0; attrs[i]; i++ )
+		int i = 0;
+		char **allattrs = NULL;
+		char **opattrs = NULL;
+		char **myattrs = NULL;
+		char **thisattr = NULL;
+		int hasstar = charray_inlist(attrs, "*");
+		int hasplus = charray_inlist(attrs, "+");
+		Slapi_Attr *objclasses = NULL;
+		Slapi_ValueSet *objclassvals = NULL;
+
+		/* get all attrs available for the entry */
+		slapi_entry_attr_find(e, "objectclass", &objclasses);
+		if (NULL != objclasses) {
+			Slapi_Value *v;
+			slapi_attr_get_valueset(objclasses, &objclassvals);
+			i = slapi_valueset_first_value(objclassvals, &v);
+			if (-1 != i) {
+				allattrs = slapi_schema_list_objectclass_attributes(
+							(const char *)v->bv.bv_val,
+							SLAPI_OC_FLAG_REQUIRED|SLAPI_OC_FLAG_ALLOWED);
+				/* add "aci" to the allattrs to adjust to do_search */
+				charray_add(&allattrs, slapi_attr_syntax_normalize("aci"));
+				while (-1 != i)
+				{
+					i = slapi_valueset_next_value(objclassvals, i, &v);
+					if (-1 != i)
+					{
+						myattrs = slapi_schema_list_objectclass_attributes(
+							(const char *)v->bv.bv_val,
+							SLAPI_OC_FLAG_REQUIRED|SLAPI_OC_FLAG_ALLOWED);
+						charray_merge_nodup(&allattrs, myattrs, 1/*copy_strs*/);
+						charray_free(myattrs);
+					}
+				}
+			}
+		}
+
+		/* get operational attrs */
+		opattrs = slapi_schema_list_attribute_names(SLAPI_ATTR_FLAG_OPATTR);
+
+		if (hasstar && hasplus)
+		{
+			GER_GET_ATTR_RIGHTS(allattrs);
+			GER_GET_ATTR_RIGHTS(opattrs);
+		}
+		else if (hasstar)
 		{
-			_ger_get_attr_rights ( gerpb, e, subjectndn, attrs[i], gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf );
-			isfirstattr = 0;
+			GER_GET_ATTR_RIGHTS(allattrs);
+			GER_GET_ATTR_RIGHTA_EXT('*', opattrs, allattrs);
 		}
+		else if (hasplus)
+		{
+			GER_GET_ATTR_RIGHTS(opattrs);
+			GER_GET_ATTR_RIGHTA_EXT('+', allattrs, opattrs);
+		}
+		else
+		{
+			for ( i = 0; attrs[i]; i++ )
+			{
+				if (charray_inlist(allattrs, attrs[i]) ||
+					charray_inlist(opattrs, attrs[i]))
+				{
+					_ger_get_attr_rights ( gerpb, e, subjectndn, attrs[i],
+						gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf );
+					isfirstattr = 0;
+				}
+			}
+		}
+		charray_free(allattrs);
+		charray_free(opattrs);
 	}
 	else
 	{
@@ -569,7 +681,8 @@
 			if ( ! slapi_attr_flag_is_set (attr, SLAPI_ATTR_FLAG_OPATTR) )
 			{
 				slapi_attr_get_type ( attr, &type );
-				_ger_get_attr_rights ( gerpb, e, subjectndn, type, gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf );
+				_ger_get_attr_rights ( gerpb, e, subjectndn, type, gerstr,
+								gerstrsize, gerstrcap, isfirstattr, errbuf );
 				isfirstattr = 0;
 			}
 			prevattr = attr;
@@ -648,6 +761,131 @@
 }
 
 int
+_ger_generate_template_entry (
+	Slapi_PBlock    *pb
+	)
+{
+	Slapi_Entry	*e = NULL;
+	char **gerattrs = NULL;
+	char **attrs = NULL;
+	char *templateentry = NULL;
+	char *object = NULL;
+	char *superior = NULL;
+	char *p = NULL;
+	int siz = 0;
+	int len = 0;
+	int i = 0;
+	int notfirst = 0;
+	int rc = LDAP_SUCCESS;
+
+	slapi_pblock_get( pb, SLAPI_SEARCH_GERATTRS, &gerattrs );
+	if (NULL == gerattrs)
+	{
+		slapi_log_error (SLAPI_LOG_FATAL, plugin_name,
+						"Objectclass info is expected "
+						"in the attr list, e.g., \"*@person\"\n");
+		rc = LDAP_SUCCESS;
+		goto bailout;
+	}
+	for (i = 0; gerattrs && gerattrs[i]; i++)
+	{
+		object = strchr(gerattrs[i], '@');
+		if (NULL != object && '\0' != *(++object))
+		{
+			break;
+		}
+	}
+	if (NULL == object)
+	{
+		rc = LDAP_SUCCESS;	/* no objectclass info; ok to return */
+		goto bailout;
+	}
+	attrs = slapi_schema_list_objectclass_attributes(
+						(const char *)object, SLAPI_OC_FLAG_REQUIRED);
+	if (NULL == attrs)
+	{
+		rc = LDAP_SUCCESS;	/* bogus objectclass info; ok to return */
+		goto bailout;
+	}
+	for (i = 0; attrs[i]; i++)
+	{
+		if (0 == strcasecmp(attrs[i], "objectclass"))
+		{
+			/* <*attrp>: <object>\n\0 */
+			siz += strlen(attrs[i]) + 4 + strlen(object);
+		}
+		else
+		{
+			/* <*attrp>: dummy\n\0 */
+			siz += strlen(attrs[i]) + 4 + 5;
+		}
+	}
+	siz += 32 + strlen(object); /* dn: cn=<template_name>\n\0 */
+	templateentry = (char *)slapi_ch_malloc(siz);
+	PR_snprintf(templateentry, siz,
+					"dn: cn=template_%s_objectclass\n", object);
+	for (--i; i >= 0; i--)
+	{
+		len = strlen(templateentry);
+		p = templateentry + len;
+		if (0 == strcasecmp(attrs[i], "objectclass"))
+		{
+			PR_snprintf(p, siz - len, "%s: %s\n", attrs[i], object);
+		}
+		else
+		{
+			PR_snprintf(p, siz - len, "%s: dummy\n", attrs[i]);
+		}
+	}
+	charray_free(attrs);
+
+	while ((superior = slapi_schema_get_superior_name(object)) &&
+			(0 != strcasecmp(superior, "top")))
+	{
+		if (notfirst)
+		{
+			slapi_ch_free_string(&object);
+		}
+		notfirst = 1;
+		object = superior;
+		attrs = slapi_schema_list_objectclass_attributes(
+						(const char *)superior, SLAPI_OC_FLAG_REQUIRED);
+		for (i = 0; attrs && attrs[i]; i++)
+		{
+			if (0 == strcasecmp(attrs[i], "objectclass"))
+			{
+				/* <*attrp>: <object>\n\0 */
+				siz += strlen(attrs[i]) + 4 + strlen(object);
+			}
+		}
+		templateentry = (char *)slapi_ch_realloc(templateentry, siz);
+		for (--i; i >= 0; i--)
+		{
+			len = strlen(templateentry);
+			p = templateentry + len;
+			if (0 == strcasecmp(attrs[i], "objectclass"))
+			{
+				PR_snprintf(p, siz - len, "%s: %s\n", attrs[i], object);
+			}
+		}
+		charray_free(attrs);
+	}
+	slapi_ch_free_string(&superior);
+	siz += 18; /* objectclass: top\n\0 */
+	len = strlen(templateentry);
+	templateentry = (char *)slapi_ch_realloc(templateentry, siz);
+	p = templateentry + len;
+	PR_snprintf(p, siz - len, "objectclass: top\n");
+
+	e = slapi_str2entry(templateentry, SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF);
+	/* set the template entry to send the result to clients */
+	slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, e);
+bailout:
+	slapi_ch_free_string(&templateentry);
+	return rc;
+}
+
+int
 acl_get_effective_rights (
 	Slapi_PBlock    *pb,
 	Slapi_Entry	    *e,			/* target entry */
@@ -664,10 +902,20 @@
 	size_t gerstrsize = 0;
 	size_t gerstrcap = 0;
 	int iscritical = 1;
-	int rc;
+	int rc = LDAP_SUCCESS;
 
 	*errbuf = '\0';
 
+	if (NULL == e)	/* create a template entry from SLAPI_SEARCH_GERATTRS */
+	{
+		rc = _ger_generate_template_entry ( pb );
+		slapi_pblock_get ( pb, SLAPI_SEARCH_RESULT_ENTRY, &e );
+		if ( rc != LDAP_SUCCESS || NULL == e )
+		{
+			goto bailout;
+		}
+	}
+
 	/*
 	 * Get the subject
 	 */
@@ -681,7 +929,7 @@
 	 * The requestor should have g permission on the entry
 	 * to get the effective rights.
 	 */
-	rc = _ger_g_permission_granted (pb, e, errbuf);
+	rc = _ger_g_permission_granted (pb, e, subjectndn, errbuf);
 	if ( rc != LDAP_SUCCESS )
 	{
 		goto bailout;
@@ -718,7 +966,7 @@
 
 	slapi_log_error (SLAPI_LOG_ACLSUMMARY, plugin_name,
 		"###### Effective Rights on Entry (%s) for Subject (%s) ######\n",
-		slapi_entry_get_ndn (e), subjectndn);
+		e?slapi_entry_get_ndn(e):"null", subjectndn?subjectndn:"null");
 	slapi_log_error (SLAPI_LOG_ACLSUMMARY, plugin_name, "%s\n", gerstr);
 
 	/* Restore pb */




More information about the Fedora-directory-commits mailing list