ldap/servers/plugins/acl/acleffectiverights.c | 57 +++++++++++++++++++++-----
ldap/servers/plugins/acl/aclparse.c | 16 ++++++-
2 files changed, 63 insertions(+), 10 deletions(-)
New commits:
commit 90f26ece2e880008cb23b2593040314196a70561
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Mon Jan 3 16:30:51 2011 -0800
Bug 664563 - GER: ger for non-present entry is not correct
https://bugzilla.redhat.com/show_bug.cgi?id=664563
Description: To get the effective rights of non-present entry,
GER code takes @<objectclass> as a part of an attribute list
in the search. The code was generating the temporary, non-
present entry with the leaf RDN "cn=<value>". Instead of
"cn",
an attribute type belonging to the objectclass whould be used.
This patch changes to allow either @<objectclass> or
@<objectclass>:<dntype>. If @<objectclass> is given, the first
MUST attribute type (or the first MAY attribute type if MUST
does not exist) is used for the attribyte type in the leaf RDN.
If @<objectclass>:<dntype> is given, <dntype> is used.
Plus, acl_check_for_target_macro in aclparse.c now checks an
invalid macro syntax [($dn)] and returns a syntax error.
diff --git a/ldap/servers/plugins/acl/acleffectiverights.c
b/ldap/servers/plugins/acl/acleffectiverights.c
index 0335a1e..a866664 100644
--- a/ldap/servers/plugins/acl/acleffectiverights.c
+++ b/ldap/servers/plugins/acl/acleffectiverights.c
@@ -612,7 +612,12 @@ _ger_get_attrs_rights (
/* gerstr was initially allocated with enough space for one more line */
_append_gerstr(gerstr, gerstrsize, gerstrcap, "attributeLevelRights: ",
NULL);
- if (attrs && *attrs)
+ /*
+ * If it's stated attribute list is given,
+ * the first attr in the list should not be empty.
+ * Otherwise, it's considered the list is not given.
+ */
+ if (attrs && *attrs && (strlen(*attrs) > 0))
{
int i = 0;
char **allattrs = NULL;
@@ -674,6 +679,9 @@ _ger_get_attrs_rights (
{
for ( i = 0; attrs[i]; i++ )
{
+ if ('\0' == *attrs[i]) {
+ continue; /* skip an empty attr */
+ }
_ger_get_attr_rights ( gerpb, e, subjectndn, attrs[i], gerstr,
gerstrsize, gerstrcap, isfirstattr, errbuf );
isfirstattr = 0;
@@ -700,6 +708,9 @@ _ger_get_attrs_rights (
{
for ( i = 0; attrs[i]; i++ )
{
+ if ('\0' == *attrs[i]) {
+ continue; /* skip an empty attr */
+ }
if (charray_inlist(allattrs, attrs[i]) ||
charray_inlist(opattrs, attrs[i]) ||
(0 == strcasecmp(attrs[i], "dn")) ||
@@ -824,11 +835,13 @@ _ger_generate_template_entry (
Slapi_Entry *e = NULL;
char **gerattrs = NULL;
char **attrs = NULL;
+ char **allowedattrs = NULL;
char *templateentry = NULL;
char *object = NULL;
char *superior = NULL;
char *p = NULL;
char *dn = NULL;
+ char *dntype = NULL;
int siz = 0;
int len = 0;
int i = 0;
@@ -859,10 +872,26 @@ _ger_generate_template_entry (
rc = LDAP_SUCCESS; /* no objectclass info; ok to return */
goto bailout;
}
+ /*
+ * Either @objectclass or @objectclass:dntype is accepted.
+ * If @objectclass, the first MUST attributetype (or the first MAY
+ * attributetype if MUST does not exist) is used for the attribute
+ * type in the leaf RDN.
+ * If @objectclass:dntype, dntype is used for the attribute type in the
+ * leaf RDN.
+ */
+ dntype = strchr(object, ':');
+ if (dntype) { /* @objectclasse:dntype */
+ *dntype++ = '\0';
+ }
+
attrs = slapi_schema_list_objectclass_attributes(
(const char *)object, SLAPI_OC_FLAG_REQUIRED);
- if (NULL == attrs)
- {
+ allowedattrs = slapi_schema_list_objectclass_attributes(
+ (const char *)object, SLAPI_OC_FLAG_ALLOWED);
+ charray_merge(&attrs, allowedattrs, 0 /* no copy */);
+ slapi_ch_free((void **)&allowedattrs); /* free just allowedattrs */
+ if (NULL == attrs) {
rc = LDAP_SUCCESS; /* bogus objectclass info; ok to return */
goto bailout;
}
@@ -881,24 +910,34 @@ _ger_generate_template_entry (
}
if (dn)
{
- /* dn: cn=<template_name>,<dn>\n\0 */
- siz += 32 + strlen(object) + strlen(dn);
+ /* dn: <attr>=<template_name>,<dn>\n\0 */
+ if (dntype) {
+ siz += strlen(dntype) + 30 + strlen(object) + strlen(dn);
+ } else {
+ siz += strlen(attrs[0]) + 30 + strlen(object) + strlen(dn);
+ }
}
else
{
- /* dn: cn=<template_name>\n\0 */
- siz += 32 + strlen(object);
+ /* dn: <attr>=<template_name>\n\0 */
+ if (dntype) {
+ siz += strlen(dntype) + 30 + strlen(object);
+ } else {
+ siz += strlen(attrs[0]) + 30 + strlen(object);
+ }
}
templateentry = (char *)slapi_ch_malloc(siz);
if (NULL != dn && strlen(dn) > 0)
{
PR_snprintf(templateentry, siz,
- "dn: cn=template_%s_objectclass,%s\n", object, dn);
+ "dn: %s=template_%s_objectclass,%s\n",
+ dntype?dntype:attrs[0], object, dn);
}
else
{
PR_snprintf(templateentry, siz,
- "dn: cn=template_%s_objectclass\n", object);
+ "dn: %s=template_%s_objectclass\n",
+ dntype?dntype:attrs[0], object);
}
for (--i; i >= 0; i--)
{
diff --git a/ldap/servers/plugins/acl/aclparse.c b/ldap/servers/plugins/acl/aclparse.c
index 05ffe50..04a1df6 100644
--- a/ldap/servers/plugins/acl/aclparse.c
+++ b/ldap/servers/plugins/acl/aclparse.c
@@ -1638,9 +1638,23 @@ acl_check_for_target_macro( aci_t *aci_item, char *value)
char *str = NULL;
- str = strstr( value, ACL_TARGET_MACRO_DN_KEY);
+ str = strstr(value, ACL_TARGET_MACRO_DN_KEY /* ($dn) */);
if (str != NULL) {
+ char *p0 = NULL, p1 = NULL;
+ /* Syntax check:
+ * error return if ($dn) is in '[' and ']', e.g., "[($dn)]"
*/
+ p0 = strchr(value, '[');
+ if (p0 && p0 < str) {
+ p1 = strchr(value, ']');
+ if (p1 && p1 < str) {
+ /* [...] ... ($dn) : good */
+ ;
+ } else {
+ /* [...($dn)...] or [...($dn... : bad */
+ return -1;
+ }
+ }
aci_item->aci_type &= ~ACI_TARGET_DN;
aci_item->aci_type |= ACI_TARGET_MACRO_DN;
aci_item->aci_macro = (aciMacro *)slapi_ch_malloc(sizeof(aciMacro));