summaryrefslogtreecommitdiffstats
path: root/ldap/servers
diff options
context:
space:
mode:
authorNoriko Hosoi <nhosoi@redhat.com>2008-06-27 19:28:22 +0000
committerNoriko Hosoi <nhosoi@redhat.com>2008-06-27 19:28:22 +0000
commit70425fbcea96d1b477fea27eca67fb7e828c446e (patch)
tree7142ac3a793a263cafbd486458fcaeb7c092e54d /ldap/servers
parentb643fa2279635381cdb0ff6d62f39b93f6a6e22f (diff)
downloadds-70425fbcea96d1b477fea27eca67fb7e828c446e.tar.gz
ds-70425fbcea96d1b477fea27eca67fb7e828c446e.tar.xz
ds-70425fbcea96d1b477fea27eca67fb7e828c446e.zip
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
Diffstat (limited to 'ldap/servers')
-rw-r--r--ldap/servers/plugins/acl/acleffectiverights.c274
-rw-r--r--ldap/servers/plugins/chainingdb/cb_config.c6
-rw-r--r--ldap/servers/plugins/chainingdb/cb_controls.c2
-rw-r--r--ldap/servers/plugins/chainingdb/cb_instance.c6
-rw-r--r--ldap/servers/plugins/schema_reload/schema_reload.c2
-rw-r--r--ldap/servers/slapd/charray.c52
-rw-r--r--ldap/servers/slapd/opshared.c225
-rw-r--r--ldap/servers/slapd/pblock.c12
-rw-r--r--ldap/servers/slapd/result.c30
-rw-r--r--ldap/servers/slapd/schema.c122
-rw-r--r--ldap/servers/slapd/search.c329
-rw-r--r--ldap/servers/slapd/slapi-plugin.h4
-rw-r--r--ldap/servers/slapd/slapi-private.h13
13 files changed, 824 insertions, 253 deletions
diff --git a/ldap/servers/plugins/acl/acleffectiverights.c b/ldap/servers/plugins/acl/acleffectiverights.c
index c40840a5..c50807f9 100644
--- a/ldap/servers/plugins/acl/acleffectiverights.c
+++ b/ldap/servers/plugins/acl/acleffectiverights.c
@@ -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 @@ _append_gerstr(char **gerstr, size_t *capacity, size_t *size, const char *news,
}
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 @@ _ger_g_permission_granted ( Slapi_PBlock *pb, Slapi_Entry *e, char **errbuf )
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 @@ bailout:
}
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 @@ _ger_parse_control ( Slapi_PBlock *pb, char **subjectndn, int *iscritical, char
* (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 @@ _ger_parse_control ( Slapi_PBlock *pb, char **subjectndn, int *iscritical, char
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 @@ _ger_get_attr_rights (
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 @@ _ger_get_attrs_rights (
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(allattrs);
+ GER_GET_ATTR_RIGHTA_EXT('*', opattrs, allattrs);
+ }
+ else if (hasplus)
{
- _ger_get_attr_rights ( gerpb, e, subjectndn, attrs[i], gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf );
- isfirstattr = 0;
+ 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 @@ _ger_get_attrs_rights (
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 @@ bailout:
}
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 @@ acl_get_effective_rights (
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 @@ acl_get_effective_rights (
* 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 @@ bailout:
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 */
diff --git a/ldap/servers/plugins/chainingdb/cb_config.c b/ldap/servers/plugins/chainingdb/cb_config.c
index f2846b49..f95723ff 100644
--- a/ldap/servers/plugins/chainingdb/cb_config.c
+++ b/ldap/servers/plugins/chainingdb/cb_config.c
@@ -477,7 +477,8 @@ cb_config_modify_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr
} else
if ( (mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_DELETE) {
charray_remove(cb->config.chaining_components,
- slapi_dn_normalize(slapi_ch_strdup(config_attr_value)));
+ slapi_dn_normalize(slapi_ch_strdup(config_attr_value)),
+ 0 /* freeit */);
}
}
if (NULL == mods[i]->mod_bvalues) {
@@ -513,7 +514,8 @@ cb_config_modify_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr
if ( (mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_DELETE) {
charray_remove(cb->config.chainable_components,
slapi_dn_normalize(slapi_ch_strdup(config_attr_value)
-));
+),
+ 0 /* freeit */);
}
}
if (NULL == mods[i]->mod_bvalues) {
diff --git a/ldap/servers/plugins/chainingdb/cb_controls.c b/ldap/servers/plugins/chainingdb/cb_controls.c
index 3c79f1cc..ca64595c 100644
--- a/ldap/servers/plugins/chainingdb/cb_controls.c
+++ b/ldap/servers/plugins/chainingdb/cb_controls.c
@@ -91,7 +91,7 @@ cb_unregister_supported_control( cb_backend * cb, char *controloid, unsigned lon
return;
}
if ( controlops == 0 ) {
- charray_remove(cb->config.forward_ctrls,controloid);
+ charray_remove(cb->config.forward_ctrls,controloid,0/* free it */);
}
PR_RWLock_Unlock(cb->config.rwl_config_lock);
}
diff --git a/ldap/servers/plugins/chainingdb/cb_instance.c b/ldap/servers/plugins/chainingdb/cb_instance.c
index 91da2aab..13791c0c 100644
--- a/ldap/servers/plugins/chainingdb/cb_instance.c
+++ b/ldap/servers/plugins/chainingdb/cb_instance.c
@@ -392,7 +392,8 @@ int cb_instance_modify_config_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefor
} else
if ( (mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_DELETE) {
charray_remove(inst->illegal_attributes,
- slapi_ch_strdup(config_attr_value));
+ slapi_ch_strdup(config_attr_value),
+ 0 /* freeit */);
}
}
if (NULL == mods[i]->mod_bvalues) {
@@ -426,7 +427,8 @@ int cb_instance_modify_config_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefor
} else
if ( (mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_DELETE) {
charray_remove(inst->chaining_components,
- slapi_dn_normalize(slapi_ch_strdup(config_attr_value)));
+ slapi_dn_normalize(slapi_ch_strdup(config_attr_value)),
+ 0 /* freeit */);
}
}
if (NULL == mods[i]->mod_bvalues) {
diff --git a/ldap/servers/plugins/schema_reload/schema_reload.c b/ldap/servers/plugins/schema_reload/schema_reload.c
index d4661f19..ac389cbb 100644
--- a/ldap/servers/plugins/schema_reload/schema_reload.c
+++ b/ldap/servers/plugins/schema_reload/schema_reload.c
@@ -214,10 +214,10 @@ schemareload_add(Slapi_PBlock *pb, Slapi_Entry *e,
{
PRThread *thread = NULL;
const char *cn;
+ const char *schemadir = NULL;
int rv = SLAPI_DSE_CALLBACK_OK;
Slapi_PBlock *mypb = NULL;
Slapi_Task *task = NULL;
- char *schemadir = NULL;
*returncode = LDAP_SUCCESS;
if ((cn = fetch_attr(e, "cn", NULL)) == NULL) {
diff --git a/ldap/servers/slapd/charray.c b/ldap/servers/slapd/charray.c
index 64dc1976..2f97f4d1 100644
--- a/ldap/servers/slapd/charray.c
+++ b/ldap/servers/slapd/charray.c
@@ -118,6 +118,48 @@ charray_merge(
(*a)[n + nn] = NULL;
}
+/*
+ * charray_merge_nodup:
+ * merge a string array (second arg) into the first string array
+ * unless the each string is in the first string array.
+ */
+void
+charray_merge_nodup(
+ char ***a,
+ char **s,
+ int copy_strs
+)
+{
+ int i, j, n, nn;
+ char **dupa;
+
+ if ( (s == NULL) || (s[0] == NULL) )
+ return;
+
+ for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) {
+ ; /* NULL */
+ }
+ for ( nn = 0; s[nn] != NULL; nn++ ) {
+ ; /* NULL */
+ }
+
+ dupa = (char **)slapi_ch_calloc(1, (n+nn+1) * sizeof(char *));
+ memcpy(dupa, *a, sizeof(char *) * n);
+ slapi_ch_free((void **)a);
+
+ for ( i = 0, j = 0; i < nn; i++ ) {
+ if (!charray_inlist(dupa, s[i])) { /* skip if s[i] is already in *a */
+ if ( copy_strs ) {
+ dupa[n+j] = slapi_ch_strdup( s[i] );
+ } else {
+ dupa[n+j] = s[i];
+ }
+ j++;
+ }
+ }
+ *a = dupa;
+}
+
/* Routines which don't pound on malloc. Don't interchange the arrays with the
* regular calls---they can end up freeing non-heap memory, which is wrong */
@@ -337,13 +379,15 @@ charray_print( char **a )
* Remove the char string from the array of char strings.
* Performs a case *insensitive* comparison!
* Just shunts the strings down to cover the deleted string.
- * Doesn't free up the unused memory.
+ * freeit: none zero -> free the found string
+ * : zero -> Doesn't free up the unused memory.
* Returns 1 if the entry found and removed, 0 if not.
*/
int
charray_remove(
char **a,
- const char *s
+ const char *s,
+ int freeit
)
{
int i;
@@ -353,6 +397,10 @@ charray_remove(
if ( !found && strcasecmp (a[i],s) == 0 )
{
found= 1;
+ if (freeit)
+ {
+ slapi_ch_free_string(&a[i]);
+ }
}
if (found)
{
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
index b9aec66a..6c81b5c2 100644
--- a/ldap/servers/slapd/opshared.c
+++ b/ldap/servers/slapd/opshared.c
@@ -953,67 +953,188 @@ iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result, int *pnentries)
int rc;
int attrsonly;
int done = 0;
- Slapi_Entry *e;
+ Slapi_Entry *e = NULL;
char **attrs = NULL;
slapi_pblock_get(pb, SLAPI_SEARCH_ATTRS, &attrs);
slapi_pblock_get(pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly);
- *pnentries = 0;
+ *pnentries = 0;
while (!done)
- {
- rc = be->be_next_search_entry(pb);
- if (rc < 0)
- {
- /*
- * Some exceptional condition occurred. Results have been sent, so we're finished.
- */
- if (rc == SLAPI_FAIL_DISKFULL)
- {
- operation_out_of_disk_space();
- }
- return -1;
- }
- else
- {
- slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &e);
- if (e == NULL)
- {
- /* no more entries */
- done = 1;
- continue;
- }
- }
+ {
+ Slapi_Entry *gerentry = NULL;
+ Slapi_Operation *operation;
- if (process_entry(pb, e, send_result))
- {
- /* shouldn't send this entry */
- continue;
- }
+ rc = be->be_next_search_entry(pb);
+ if (rc < 0)
+ {
+ /*
+ * Some exceptional condition occurred. Results have been sent, so we're finished.
+ */
+ if (rc == SLAPI_FAIL_DISKFULL)
+ {
+ operation_out_of_disk_space();
+ }
+ return -1;
+ }
- /*
- * It's a regular entry, or it's a referral and
- * managedsait control is on. In either case, send
- * the entry.
- */
- switch (send_ldap_search_entry(pb, e, NULL, attrs, attrsonly))
- {
- case 0: /* entry sent ok */
- (*pnentries)++;
- slapi_pblock_set(pb, SLAPI_NENTRIES, pnentries);
- break;
- case 1: /* entry not sent */
- break;
- case -1: /* connection closed */
- /*
- * mark the operation as abandoned so the backend
- * next entry function gets called again and has
- * a chance to clean things up.
- */
- pb->pb_op->o_status = SLAPI_OP_STATUS_ABANDONED;
- break;
- }
+ slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &e);
+
+ /* Check for possible get_effective_rights control */
+ slapi_pblock_get (pb, SLAPI_OPERATION, &operation);
+ if ( operation->o_flags & OP_FLAG_GET_EFFECTIVE_RIGHTS )
+ {
+ char *errbuf = NULL;
+ char **gerattrs = NULL;
+ char **gerattrsdup = NULL;
+ char **gap = NULL;
+ char *gapnext = NULL;
+
+ slapi_pblock_get( pb, SLAPI_SEARCH_GERATTRS, &gerattrs );
+
+ gerattrsdup = cool_charray_dup(gerattrs);
+ gap = gerattrsdup;
+ do
+ {
+ gapnext = NULL;
+ if (gap)
+ {
+ if (*gap && *(gap+1))
+ {
+ gapnext = *(gap+1);
+ *(gap+1) = NULL;
+ }
+ slapi_pblock_set( pb, SLAPI_SEARCH_GERATTRS, gap );
+ rc = plugin_call_acl_plugin (pb, e, attrs, NULL,
+ SLAPI_ACL_ALL, ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS,
+ &errbuf);
+ if (NULL != gapnext)
+ {
+ *(gap+1) = gapnext;
+ }
+ }
+ else if (NULL != e)
+ {
+ rc = plugin_call_acl_plugin (pb, e, attrs, NULL,
+ SLAPI_ACL_ALL, ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS,
+ &errbuf);
+ }
+ if (NULL == e) {
+ /* get the template entry, if any */
+ slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &e);
+ if (NULL == e) {
+ /* everything is ok - don't send the result */
+ return 1;
+ }
+ gerentry = e;
+ }
+ if ( rc != LDAP_SUCCESS ) {
+ /* Send error result and
+ abort op if the control is critical */
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "Failed to get effective rights for entry (%s), rc=%d\n",
+ slapi_entry_get_dn_const(e), rc, 0 );
+ send_ldap_result( pb, rc, NULL, errbuf, 0, NULL );
+ slapi_ch_free ( (void**)&errbuf );
+ if (gerentry)
+ {
+ slapi_pblock_set(pb,
+ SLAPI_SEARCH_RESULT_ENTRY, NULL);
+ slapi_entry_free(gerentry);
+ gerentry = e = NULL;
+ }
+ return( -1 );
+ }
+ slapi_ch_free ( (void**)&errbuf );
+ if (process_entry(pb, e, send_result))
+ {
+ /* shouldn't send this entry */
+ if (gerentry)
+ {
+ slapi_pblock_set(pb,
+ SLAPI_SEARCH_RESULT_ENTRY, NULL);
+ slapi_entry_free(gerentry);
+ gerentry = e = NULL;
+ }
+ continue;
+ }
+
+ /*
+ * It's a regular entry, or it's a referral and
+ * managedsait control is on. In either case, send
+ * the entry.
+ */
+ switch (send_ldap_search_entry(pb, e,
+ NULL, attrs, attrsonly))
+ {
+ case 0: /* entry sent ok */
+ (*pnentries)++;
+ slapi_pblock_set(pb, SLAPI_NENTRIES, pnentries);
+ break;
+ case 1: /* entry not sent */
+ break;
+ case -1: /* connection closed */
+ /*
+ * mark the operation as abandoned so the backend
+ * next entry function gets called again and has
+ * a chance to clean things up.
+ */
+ pb->pb_op->o_status = SLAPI_OP_STATUS_ABANDONED;
+ break;
+ }
+ if (gerentry)
+ {
+ slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
+ slapi_entry_free(gerentry);
+ gerentry = e = NULL;
+ }
+ }
+ while (gap && ++gap && *gap);
+ slapi_pblock_set( pb, SLAPI_SEARCH_GERATTRS, gerattrs );
+ cool_charray_free(gerattrsdup);
+ if (NULL == e)
+ {
+ /* no more entries */
+ done = 1;
+ }
+ }
+ else if (e)
+ {
+ if (process_entry(pb, e, send_result))
+ {
+ /* shouldn't send this entry */
+ continue;
+ }
+
+ /*
+ * It's a regular entry, or it's a referral and
+ * managedsait control is on. In either case, send
+ * the entry.
+ */
+ switch (send_ldap_search_entry(pb, e, NULL, attrs, attrsonly))
+ {
+ case 0: /* entry sent ok */
+ (*pnentries)++;
+ slapi_pblock_set(pb, SLAPI_NENTRIES, pnentries);
+ break;
+ case 1: /* entry not sent */
+ break;
+ case -1: /* connection closed */
+ /*
+ * mark the operation as abandoned so the backend
+ * next entry function gets called again and has
+ * a chance to clean things up.
+ */
+ pb->pb_op->o_status = SLAPI_OP_STATUS_ABANDONED;
+ break;
+ }
+ }
+ else
+ {
+ /* no more entries */
+ done = 1;
+ }
}
return 1;
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
index ae98dc23..987b2476 100644
--- a/ldap/servers/slapd/pblock.c
+++ b/ldap/servers/slapd/pblock.c
@@ -1231,6 +1231,12 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
(*(char ***)value) = pblock->pb_op->o_params.p.p_search.search_attrs;
}
break;
+ case SLAPI_SEARCH_GERATTRS:
+ if(pblock->pb_op!=NULL)
+ {
+ (*(char ***)value) = pblock->pb_op->o_params.p.p_search.search_gerattrs;
+ }
+ break;
case SLAPI_SEARCH_ATTRSONLY:
if(pblock->pb_op!=NULL)
{
@@ -2509,6 +2515,12 @@ slapi_pblock_set( Slapi_PBlock *pblock, int arg, void *value )
pblock->pb_op->o_params.p.p_search.search_attrs = (char **) value;
}
break;
+ case SLAPI_SEARCH_GERATTRS:
+ if(pblock->pb_op!=NULL)
+ {
+ pblock->pb_op->o_params.p.p_search.search_gerattrs = (char **) value;
+ }
+ break;
case SLAPI_SEARCH_ATTRSONLY:
if(pblock->pb_op!=NULL)
{
diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c
index 31c839d1..49331dce 100644
--- a/ldap/servers/slapd/result.c
+++ b/ldap/servers/slapd/result.c
@@ -1203,14 +1203,15 @@ send_ldap_search_entry_ext(
int *dontsendattr= NULL;
Slapi_Operation *operation;
int real_attrs_only = 0;
- LDAPControl **ctrlp = 0;
+ LDAPControl **ctrlp = 0;
+ Slapi_Entry *gerentry = NULL;
slapi_pblock_get (pb, SLAPI_OPERATION, &operation);
LDAPDebug( LDAP_DEBUG_TRACE, "=> send_ldap_search_entry (%s)\n",
- slapi_entry_get_dn_const(e), 0, 0 );
+ e?slapi_entry_get_dn_const(e):"null", 0, 0 );
- if ( conn == NULL ) {
+ if ( conn == NULL && e ) {
if ( op->o_search_entry_handler != NULL ) {
if (( rc = (*op->o_search_entry_handler)(
pb->pb_backend, conn, op, e )) == 0 ) {
@@ -1224,7 +1225,7 @@ send_ldap_search_entry_ext(
}
#if !defined(DISABLE_ACL_CHECK)
- if ( plugin_call_acl_plugin (pb, e, attrs, NULL,
+ if ( e && plugin_call_acl_plugin (pb, e, attrs, NULL,
SLAPI_ACL_READ, ACLPLUGIN_ACCESS_READ_ON_ENTRY, NULL ) != LDAP_SUCCESS ) {
LDAPDebug( LDAP_DEBUG_ACL, "acl: access to entry not allowed\n",
0, 0, 0 );
@@ -1232,21 +1233,8 @@ send_ldap_search_entry_ext(
}
#endif
- /* Check for possible get_effective_rights control */
- if ( operation->o_flags & OP_FLAG_GET_EFFECTIVE_RIGHTS ) {
- char *errbuf = NULL;
- rc = plugin_call_acl_plugin (pb, e, attrs, NULL, SLAPI_ACL_ALL,
- ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS, &errbuf);
- if ( rc != LDAP_SUCCESS ) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "Failed to get effective rights for entry (%s), rc=%d\n",
- slapi_entry_get_dn_const(e), rc, 0 );
- /* Send error result and abort op if the control is critical */
- send_ldap_result( pb, rc, NULL, errbuf, 0, NULL );
- slapi_ch_free ( (void**)&errbuf );
- return( -1 );
- }
- slapi_ch_free ( (void**)&errbuf );
+ if (NULL == e) {
+ return 1; /* everything is ok - don't send the result */
}
if ( (ber = der_alloc()) == NULL ) {
@@ -1454,6 +1442,10 @@ log_and_return:
}
}
+ if (gerentry)
+ {
+ slapi_entry_free(gerentry);
+ }
LDAPDebug( LDAP_DEBUG_TRACE, "<= send_ldap_search_entry\n", 0, 0, 0 );
exit:
return( rc );
diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c
index d116e340..b8e154af 100644
--- a/ldap/servers/slapd/schema.c
+++ b/ldap/servers/slapd/schema.c
@@ -641,41 +641,41 @@ static int
oc_check_required( Slapi_PBlock *pb, Slapi_Entry *e, struct objclass *oc )
{
int i;
- int rc = 0; /* success, by default */
+ int rc = 0; /* success, by default */
Slapi_Attr *a;
if (oc == NULL || oc->oc_required == NULL || oc->oc_required[0] == NULL) {
- return 0; /* success, as none required */
+ return 0; /* success, as none required */
}
/* for each required attribute */
for ( i = 0; oc->oc_required[i] != NULL; i++ ) {
/* see if it's in the entry */
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
- if ( slapi_attr_type_cmp( oc->oc_required[i], a->a_type,
- SLAPI_TYPE_CMP_SUBTYPE ) == 0 ) {
- break;
- }
- }
-
- /* not there => schema violation */
- if ( a == NULL ) {
- char errtext[ BUFSIZ ];
- char ebuf[ BUFSIZ ];
- LDAPDebug( LDAP_DEBUG_ANY,
- "Entry \"%s\" missing attribute \"%s\" required"
- " by object class \"%s\"\n",
- escape_string( slapi_entry_get_dn_const(e), ebuf ),
- oc->oc_required[i], oc->oc_name);
- if (pb) {
- PR_snprintf( errtext, sizeof( errtext ),
- "missing attribute \"%s\" required"
- " by object class \"%s\"\n",
- oc->oc_required[i], oc->oc_name );
- slapi_pblock_set( pb, SLAPI_PB_RESULT_TEXT, errtext );
- }
- rc = 1; /* failure */
- }
+ if ( slapi_attr_type_cmp( oc->oc_required[i], a->a_type,
+ SLAPI_TYPE_CMP_SUBTYPE ) == 0 ) {
+ break;
+ }
+ }
+
+ /* not there => schema violation */
+ if ( a == NULL ) {
+ char errtext[ BUFSIZ ];
+ char ebuf[ BUFSIZ ];
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "Entry \"%s\" missing attribute \"%s\" required"
+ " by object class \"%s\"\n",
+ escape_string( slapi_entry_get_dn_const(e), ebuf ),
+ oc->oc_required[i], oc->oc_name);
+ if (pb) {
+ PR_snprintf( errtext, sizeof( errtext ),
+ "missing attribute \"%s\" required"
+ " by object class \"%s\"\n",
+ oc->oc_required[i], oc->oc_name );
+ slapi_pblock_set( pb, SLAPI_PB_RESULT_TEXT, errtext );
+ }
+ rc = 1; /* failure */
+ }
}
return rc;
@@ -1392,8 +1392,8 @@ schema_list_attributes_callback(struct asyntaxinfo *asi, void *arg)
}
/* Return the list of attributes names matching attribute flags */
-
-char ** slapi_schema_list_attribute_names(unsigned long flag)
+char **
+slapi_schema_list_attribute_names(unsigned long flag)
{
struct listargs aew;
memset(&aew,0,sizeof(struct listargs));
@@ -4966,3 +4966,69 @@ slapi_reload_schema_files(char *schemadir)
return LDAP_LOCAL_ERROR;
}
}
+
+/*
+ * slapi_schema_list_objectclass_attributes:
+ * Return the list of attributes belonging to the objectclass
+ *
+ * The caller is responsible to free the returned list with charray_free.
+ * flags: one of them or both:
+ * SLAPI_OC_FLAG_REQUIRED
+ * SLAPI_OC_FLAG_ALLOWED
+ */
+char **
+slapi_schema_list_objectclass_attributes(const char *ocname_or_oid,
+ PRUint32 flags)
+{
+ struct objclass *oc = NULL;
+ char **attrs = NULL;
+ PRUint32 mask = SLAPI_OC_FLAG_REQUIRED | SLAPI_OC_FLAG_ALLOWED;
+
+ if (!flags) {
+ return attrs;
+ }
+
+ oc_lock_read();
+ oc = oc_find_nolock(ocname_or_oid);
+ if (oc) {
+ switch (flags & mask) {
+ case SLAPI_OC_FLAG_REQUIRED:
+ attrs = charray_dup(oc->oc_required);
+ break;
+ case SLAPI_OC_FLAG_ALLOWED:
+ attrs = charray_dup(oc->oc_allowed);
+ break;
+ case SLAPI_OC_FLAG_REQUIRED|SLAPI_OC_FLAG_ALLOWED:
+ attrs = charray_dup(oc->oc_required);
+ charray_merge(&attrs, oc->oc_allowed, 1/*copy_strs*/);
+ break;
+ default:
+ slapi_log_error( SLAPI_LOG_FATAL, "list objectclass attributes",
+ "flag 0x%x not supported\n", flags );
+ break;
+ }
+ }
+ oc_unlock();
+ return attrs;
+}
+
+/*
+ * slapi_schema_get_superior_name:
+ * Return the name of the superior objectclass
+ *
+ * The caller is responsible to free the returned name
+ */
+char *
+slapi_schema_get_superior_name(const char *ocname_or_oid)
+{
+ struct objclass *oc = NULL;
+ char *superior = NULL;
+
+ oc_lock_read();
+ oc = oc_find_nolock(ocname_or_oid);
+ if (oc) {
+ superior = slapi_ch_strdup(oc->oc_superior);
+ }
+ oc_unlock();
+ return superior;
+}
diff --git a/ldap/servers/slapd/search.c b/ldap/servers/slapd/search.c
index dcd8265c..c3d1c80d 100644
--- a/ldap/servers/slapd/search.c
+++ b/ldap/servers/slapd/search.c
@@ -65,92 +65,93 @@ void
do_search( Slapi_PBlock *pb )
{
Slapi_Operation *operation;
- BerElement *ber;
- int i, err, attrsonly;
- ber_int_t scope, deref, sizelimit, timelimit;
- char *base = NULL, *fstr = NULL;
- struct slapi_filter *filter = NULL;
- char **attrs = NULL;
- int psearch = 0;
- struct berval *psbvp;
- ber_int_t changetypes;
+ BerElement *ber;
+ int i, err, attrsonly;
+ ber_int_t scope, deref, sizelimit, timelimit;
+ char *base = NULL, *fstr = NULL;
+ struct slapi_filter *filter = NULL;
+ char **attrs = NULL;
+ char **gerattrs = NULL;
+ int psearch = 0;
+ struct berval *psbvp;
+ ber_int_t changetypes;
int send_entchg_controls;
int changesonly = 0;
int rc = -1;
char *original_base = 0;
char *new_base = 0;
- LDAPDebug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
slapi_pblock_get( pb, SLAPI_OPERATION, &operation);
- ber = operation->o_ber;
+ ber = operation->o_ber;
- /* count the search request */
- snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsSearchOps);
+ /* count the search request */
+ snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsSearchOps);
- /*
- * Parse the search request. It looks like this:
- *
- * SearchRequest := [APPLICATION 3] SEQUENCE {
- * baseObject DistinguishedName,
- * scope ENUMERATED {
- * baseObject (0),
- * singleLevel (1),
- * wholeSubtree (2)
- * },
- * derefAliases ENUMERATED {
- * neverDerefaliases (0),
- * derefInSearching (1),
- * derefFindingBaseObj (2),
- * alwaysDerefAliases (3)
- * },
- * sizelimit INTEGER (0 .. 65535),
- * timelimit INTEGER (0 .. 65535),
- * attrsOnly BOOLEAN,
- * filter Filter,
- * attributes SEQUENCE OF AttributeType
- * }
- */
+ /*
+ * Parse the search request. It looks like this:
+ *
+ * SearchRequest := [APPLICATION 3] SEQUENCE {
+ * baseObject DistinguishedName,
+ * scope ENUMERATED {
+ * baseObject (0),
+ * singleLevel (1),
+ * wholeSubtree (2)
+ * },
+ * derefAliases ENUMERATED {
+ * neverDerefaliases (0),
+ * derefInSearching (1),
+ * derefFindingBaseObj (2),
+ * alwaysDerefAliases (3)
+ * },
+ * sizelimit INTEGER (0 .. 65535),
+ * timelimit INTEGER (0 .. 65535),
+ * attrsOnly BOOLEAN,
+ * filter Filter,
+ * attributes SEQUENCE OF AttributeType
+ * }
+ */
- /* baseObject, scope, derefAliases, sizelimit, timelimit, attrsOnly */
- if ( ber_scanf( ber, "{aiiiib", &base, &scope, &deref, &sizelimit, &timelimit, &attrsonly ) == LBER_ERROR ){
- slapi_ch_free((void**)&base );
- log_search_access (pb, "???", -1, "???", "decoding error");
- send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0, NULL );
- return;
- }
+ /* baseObject, scope, derefAliases, sizelimit, timelimit, attrsOnly */
+ if ( ber_scanf( ber, "{aiiiib", &base, &scope, &deref, &sizelimit, &timelimit, &attrsonly ) == LBER_ERROR ){
+ slapi_ch_free((void**)&base );
+ log_search_access (pb, "???", -1, "???", "decoding error");
+ send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0, NULL );
+ return;
+ }
- /*
- * ignore negative time and size limits since they make no sense
- */
- if ( timelimit < 0 ) {
+ /*
+ * ignore negative time and size limits since they make no sense
+ */
+ if ( timelimit < 0 ) {
timelimit = 0;
- }
- if ( sizelimit < 0 ) {
+ }
+ if ( sizelimit < 0 ) {
sizelimit = 0;
- }
+ }
- if ( scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL
+ if ( scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL
&& scope != LDAP_SCOPE_SUBTREE ) {
log_search_access (pb, base, scope, "???", "Unknown search scope");
- send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
+ send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
"Unknown search scope", 0, NULL );
- goto free_and_return;
- }
- /* check and record the scope for snmp */
- if ( scope == LDAP_SCOPE_ONELEVEL) {
+ goto free_and_return;
+ }
+ /* check and record the scope for snmp */
+ if ( scope == LDAP_SCOPE_ONELEVEL) {
/* count the one level search request */
snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsOneLevelSearchOps);
- } else if (scope == LDAP_SCOPE_SUBTREE) {
+ } else if (scope == LDAP_SCOPE_SUBTREE) {
/* count the subtree search request */
snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsWholeSubtreeSearchOps);
- }
+ }
- /* filter - returns a "normalized" version */
- filter = NULL;
- fstr = NULL;
- if ( (err = get_filter( pb->pb_conn, ber, scope, &filter, &fstr )) != 0 ) {
+ /* filter - returns a "normalized" version */
+ filter = NULL;
+ fstr = NULL;
+ if ( (err = get_filter( pb->pb_conn, ber, scope, &filter, &fstr )) != 0 ) {
char *errtxt;
if ( LDAP_UNWILLING_TO_PERFORM == err ) {
@@ -159,18 +160,18 @@ do_search( Slapi_PBlock *pb )
errtxt = "Bad search filter";
}
log_search_access( pb, base, scope, "???", errtxt );
- send_ldap_result( pb, err, NULL, errtxt, 0, NULL );
- goto free_and_return;
- }
+ send_ldap_result( pb, err, NULL, errtxt, 0, NULL );
+ goto free_and_return;
+ }
- /* attributes */
- attrs = NULL;
- if ( ber_scanf( ber, "{v}}", &attrs ) == LBER_ERROR ) {
+ /* attributes */
+ attrs = NULL;
+ if ( ber_scanf( ber, "{v}}", &attrs ) == LBER_ERROR ) {
log_search_access (pb, base, scope, fstr, "decoding error");
- send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0,
+ send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0,
NULL );
- goto free_and_return;
- }
+ goto free_and_return;
+ }
/*
* This search is performed against the legacy consumer, so ask explicitly
@@ -186,56 +187,128 @@ do_search( Slapi_PBlock *pb )
charray_add(&attrs, slapi_attr_syntax_normalize("aci"));
charray_add(&attrs, slapi_attr_syntax_normalize(LDAP_ALL_USER_ATTRS));
}
- else
+ }
+
+ if ( attrs != NULL ) {
+ int gerattrsiz = 1;
+ int gerattridx = 0;
+ int aciin = 0;
+ /*
+ * . store gerattrs if any
+ * . add "aci" once if "*" is given
+ */
+ for ( i = 0; attrs[i] != NULL; i++ )
{
- for ( i = 0; attrs[i] != NULL; i++ )
+ char *p = NULL;
+ /* check if @<objectclass> is included */
+ p = strchr(attrs[i], '@');
+ if ( p && '\0' != *(p+1) ) /* don't store "*@", e.g. */
{
- if ( strcasecmp(attrs[i], LDAP_ALL_USER_ATTRS) == 0 )
+ int j = 0;
+ if (gerattridx + 1 >= gerattrsiz)
+ {
+ char **tmpgerattrs;
+ gerattrsiz *= 2;
+ tmpgerattrs =
+ (char **)slapi_ch_calloc(1, gerattrsiz*sizeof(char *));
+ if (NULL != gerattrs)
+ {
+ memcpy(tmpgerattrs, gerattrs, gerattrsiz*sizeof(char *));
+ slapi_ch_free((void **)&gerattrs);
+ }
+ gerattrs = tmpgerattrs;
+ }
+ for ( j = 0; gerattrs; j++ )
{
- charray_add(&attrs, slapi_attr_syntax_normalize("aci"));
- break;
+ char *attri = NULL;
+ if ( NULL == gerattrs[j] )
+ {
+ if (0 == j)
+ {
+ /* first time */
+ gerattrs[gerattridx++] = attrs[i];
+ /* get rid of "@<objectclass>" part from the attr
+ list, which is needed only in gerattr list */
+ *p = '\0';
+ attri = slapi_ch_strdup(attrs[i]);
+ attrs[i] = attri;
+ *p = '@';
+ }
+ else
+ {
+ break; /* done */
+ }
+ }
+ else if ( 0 == strcasecmp( attrs[i], gerattrs[j] ))
+ {
+ /* skip if attrs[i] is already in gerattrs */
+ continue;
+ }
+ else
+ {
+ char *q = strchr(gerattrs[j], '@'); /* q never be 0 */
+ if ( 0 != strcasecmp( p+1, q+1 ))
+ {
+ /* you don't want to display the same template
+ entry multiple times */
+ gerattrs[gerattridx++] = attrs[i];
+ }
+ /* get rid of "@<objectclass>" part from the attr
+ list, which is needed only in gerattr list */
+ *p = '\0';
+ attri = slapi_ch_strdup(attrs[i]);
+ attrs[i] = attri;
+ *p = '@';
+ }
}
}
+ else if ( !aciin && strcasecmp(attrs[i], LDAP_ALL_USER_ATTRS) == 0 )
+ {
+ charray_add(&attrs, slapi_attr_syntax_normalize("aci"));
+ aciin = 1;
+ }
+ }
+ if (NULL != gerattrs)
+ {
+ gerattrs[gerattridx] = NULL;
}
- }
- if ( attrs != NULL ) {
- operation->o_searchattrs = cool_charray_dup( attrs );
- for ( i = 0; attrs[i] != NULL; i++ ) {
- char *type;
+ operation->o_searchattrs = cool_charray_dup( attrs );
+ for ( i = 0; attrs[i] != NULL; i++ ) {
+ char *type;
- type = slapi_attr_syntax_normalize(attrs[i]);
- slapi_ch_free( (void**)&(attrs[i]) );
- attrs[i] = type;
- }
- }
- if ( slapd_ldap_debug & LDAP_DEBUG_ARGS ) {
- char abuf[ 1024 ], *astr;
+ type = slapi_attr_syntax_normalize(attrs[i]);
+ slapi_ch_free( (void**)&(attrs[i]) );
+ attrs[i] = type;
+ }
+ }
+ if ( slapd_ldap_debug & LDAP_DEBUG_ARGS ) {
+ char abuf[ 1024 ], *astr;
- if ( NULL == attrs ) {
- astr = "ALL";
- } else {
- strarray2str( attrs, abuf, sizeof( abuf ), 1 /* include quotes */);
- astr = abuf;
+ if ( NULL == attrs ) {
+ astr = "ALL";
+ } else {
+ strarray2str( attrs, abuf, sizeof( abuf ), 1 /* include quotes */);
+ astr = abuf;
+ }
+ slapi_log_error( SLAPI_LOG_ARGS, NULL, "SRCH base=\"%s\" "
+ "scope=%d deref=%d "
+ "sizelimit=%d timelimit=%d attrsonly=%d filter=\"%s\" "
+ "attrs=%s\n", base, scope, deref, sizelimit, timelimit,
+ attrsonly, fstr, astr );
}
- slapi_log_error( SLAPI_LOG_ARGS, NULL, "SRCH base=\"%s\" "
- "scope=%d deref=%d "
- "sizelimit=%d timelimit=%d attrsonly=%d filter=\"%s\" "
- "attrs=%s\n", base, scope, deref, sizelimit, timelimit,
- attrsonly, fstr, astr );
- }
- /*
- * in LDAPv3 there can be optional control extensions on
- * the end of an LDAPMessage. we need to read them in and
- * pass them to the backend. get_ldapmessage_controls()
- * reads the controls and sets any we know about in the pb.
- */
- if ( (err = get_ldapmessage_controls( pb, ber, NULL )) != 0 ) {
+ /*
+ * in LDAPv3 there can be optional control extensions on
+ * the end of an LDAPMessage. we need to read them in and
+ * pass them to the backend. get_ldapmessage_controls()
+ * reads the controls and sets any we know about in the pb.
+ */
+ if ( (err = get_ldapmessage_controls( pb, ber, NULL )) != 0 ) {
log_search_access (pb, base, scope, fstr, "failed to decode LDAP controls");
- send_ldap_result( pb, err, NULL, NULL, 0, NULL );
- goto free_and_return;
- }
+ send_ldap_result( pb, err, NULL, NULL, 0, NULL );
+ goto free_and_return;
+ }
/* we support persistent search for regular operations only */
if ( slapi_control_present( operation->o_params.request_controls,
@@ -254,15 +327,16 @@ do_search( Slapi_PBlock *pb )
}
}
- slapi_pblock_set( pb, SLAPI_SEARCH_TARGET, base );
+ slapi_pblock_set( pb, SLAPI_SEARCH_TARGET, base );
slapi_pblock_set( pb, SLAPI_ORIGINAL_TARGET_DN, slapi_ch_strdup(base) );
- slapi_pblock_set( pb, SLAPI_SEARCH_SCOPE, &scope );
- slapi_pblock_set( pb, SLAPI_SEARCH_DEREF, &deref );
- slapi_pblock_set( pb, SLAPI_SEARCH_FILTER, filter );
- slapi_pblock_set( pb, SLAPI_SEARCH_STRFILTER, fstr );
- slapi_pblock_set( pb, SLAPI_SEARCH_ATTRS, attrs );
- slapi_pblock_set( pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly );
- slapi_pblock_set( pb, SLAPI_REQUESTOR_ISROOT, &operation->o_isroot );
+ slapi_pblock_set( pb, SLAPI_SEARCH_SCOPE, &scope );
+ slapi_pblock_set( pb, SLAPI_SEARCH_DEREF, &deref );
+ slapi_pblock_set( pb, SLAPI_SEARCH_FILTER, filter );
+ slapi_pblock_set( pb, SLAPI_SEARCH_STRFILTER, fstr );
+ slapi_pblock_set( pb, SLAPI_SEARCH_ATTRS, attrs );
+ slapi_pblock_set( pb, SLAPI_SEARCH_GERATTRS, gerattrs );
+ slapi_pblock_set( pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly );
+ slapi_pblock_set( pb, SLAPI_REQUESTOR_ISROOT, &operation->o_isroot );
slapi_pblock_set( pb, SLAPI_SEARCH_SIZELIMIT, &sizelimit );
slapi_pblock_set( pb, SLAPI_SEARCH_TIMELIMIT, &timelimit );
@@ -277,23 +351,22 @@ do_search( Slapi_PBlock *pb )
slapi_pblock_get(pb, SLAPI_SEARCH_TARGET, &new_base);
slapi_pblock_get (pb, SLAPI_PLUGIN_OPRETURN, &rc);
- slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter );
+ slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter );
- if ( psearch && rc == 0 ) {
+ if ( psearch && rc == 0 ) {
ps_add( pb, changetypes, send_entchg_controls );
- }
+ }
free_and_return:;
- if ( !psearch || rc < 0 ) {
+ if ( !psearch || rc < 0 ) {
if(original_base != new_base) {
slapi_ch_free_string(&new_base);
}
- slapi_ch_free_string(&base);
- slapi_ch_free_string(&fstr);
- slapi_filter_free( filter, 1 );
- if ( attrs != NULL ) {
- charray_free( attrs );
- }
+ slapi_ch_free_string(&base);
+ slapi_ch_free_string(&fstr);
+ slapi_filter_free( filter, 1 );
+ charray_free( attrs ); /* passing NULL is fine */
+ charray_free( gerattrs ); /* passing NULL is fine */
/*
* Fix for defect 526719 / 553356 : Persistent search op failed.
* Marking it as non-persistent so that operation resources get freed
@@ -304,7 +377,7 @@ free_and_return:;
/* we strdup'd this above - need to free */
slapi_pblock_get(pb, SLAPI_ORIGINAL_TARGET_DN, &base);
slapi_ch_free_string(&base);
- }
+ }
}
static void log_search_access (Slapi_PBlock *pb, const char *base, int scope, const char *fstr, const char *msg)
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 26733b1f..92cac83c 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -72,6 +72,9 @@ extern "C" {
#define SLAPI_OP_FLAG_NEVER_CHAIN 0x00800 /* Do not chain the operation */
#define SLAPI_OP_FLAG_NO_ACCESS_CHECK 0x10000 /* Do not check for access control - bypass them */
+#define SLAPI_OC_FLAG_REQUIRED 0x0001
+#define SLAPI_OC_FLAG_ALLOWED 0x0002
+
/*
* access control levels
*/
@@ -1703,6 +1706,7 @@ typedef struct slapi_plugindesc {
#define SLAPI_SEARCH_FILTER 114
#define SLAPI_SEARCH_STRFILTER 115
#define SLAPI_SEARCH_ATTRS 116
+#define SLAPI_SEARCH_GERATTRS 1160
#define SLAPI_SEARCH_ATTRSONLY 117
#define SLAPI_SEARCH_IS_AND 118
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
index 59e95d4a..8d16deee 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -574,6 +574,7 @@ typedef struct slapi_operation_parameters
char **search_attrs;
int search_attrsonly;
int search_is_and;
+ char **search_gerattrs;
} p_search;
struct abandon_parameters
@@ -726,6 +727,11 @@ struct slapi_componentid * plugin_get_default_component_id();
/* return the list of attr defined in the schema matching the attr flags */
char ** slapi_schema_list_attribute_names(unsigned long flag);
+/* return the list of attributes belonging to the objectclass */
+char ** slapi_schema_list_objectclass_attributes(const char *ocname_or_oid,
+ PRUint32 flags);
+char * slapi_schema_get_superior_name(const char *ocname_or_oid);
+
CSN *dup_global_schema_csn();
/* misc function for the chaining backend */
@@ -787,13 +793,14 @@ int slapi_config_get_readonly();
*/
void charray_add( char ***a, char *s );
void charray_merge( char ***a, char **s, int copy_strs );
+void charray_merge_nodup( char ***a, char **s, int copy_strs );
void charray_free( char **array );
int charray_inlist( char **a, char *s );
int charray_utf8_inlist( char **a, char *s );
char ** charray_dup( char **a );
char ** str2charray( char *str, char *brkstr );
char ** str2charray_ext( char *str, char *brkstr, int allow_dups );
-int charray_remove(char **a,const char *s);
+int charray_remove(char **a, const char *s, int freeit);
char ** cool_charray_dup( char **a );
void cool_charray_free( char **array );
void charray_subtract( char **a, char **b, char ***c );
@@ -1124,10 +1131,6 @@ char* slapd_get_tmp_dir( void );
const char* escape_string (const char* str, char buf[BUFSIZ]);
const char* escape_string_with_punctuation(const char* str, char buf[BUFSIZ]);
const char* escape_filter_value(const char* str, int len, char buf[BUFSIZ]);
-void charray_add( char ***a, char *s );
-void charray_free(char **array);
-int charray_remove(char **a,const char *s);
-int charray_inlist( char **a, char *s );
char *slapi_berval_get_string_copy(const struct berval *bval);