Author: nhosoi
Update of /cvs/dirsec/ldapserver/ldap/servers/slapd
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv6584/ldap/servers/slapd
Modified Files:
charray.c opshared.c pblock.c result.c schema.c search.c
slapi-plugin.h slapi-private.h
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-pres...
Index: charray.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/charray.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- charray.c 10 Nov 2006 23:45:40 -0000 1.6
+++ charray.c 27 Jun 2008 19:28:21 -0000 1.7
@@ -118,6 +118,48 @@
(*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 @@
* 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 @@
if ( !found && strcasecmp (a[i],s) == 0 )
{
found= 1;
+ if (freeit)
+ {
+ slapi_ch_free_string(&a[i]);
+ }
}
if (found)
{
Index: opshared.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/opshared.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- opshared.c 18 Oct 2007 00:08:34 -0000 1.11
+++ opshared.c 27 Jun 2008 19:28:21 -0000 1.12
@@ -953,67 +953,188 @@
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;
- }
- }
-
- 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;
- }
+ {
+ Slapi_Entry *gerentry = NULL;
+ Slapi_Operation *operation;
+
+ 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;
+ }
+
+ 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;
Index: pblock.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/pblock.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- pblock.c 4 Jun 2008 22:22:55 -0000 1.13
+++ pblock.c 27 Jun 2008 19:28:21 -0000 1.14
@@ -1231,6 +1231,12 @@
(*(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 @@
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)
{
Index: result.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/result.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- result.c 18 Oct 2007 00:08:34 -0000 1.12
+++ result.c 27 Jun 2008 19:28:21 -0000 1.13
@@ -1203,14 +1203,15 @@
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 @@
}
#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 @@
}
#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 @@
}
}
+ if (gerentry)
+ {
+ slapi_entry_free(gerentry);
+ }
LDAPDebug( LDAP_DEBUG_TRACE, "<= send_ldap_search_entry\n", 0, 0, 0 );
exit:
return( rc );
Index: schema.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/schema.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- schema.c 10 Jun 2008 18:50:07 -0000 1.14
+++ schema.c 27 Jun 2008 19:28:21 -0000 1.15
@@ -641,41 +641,41 @@
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 @@
}
/* 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 @@
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;
+}
Index: search.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/search.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- search.c 18 Oct 2007 00:08:34 -0000 1.8
+++ search.c 27 Jun 2008 19:28:21 -0000 1.9
@@ -65,92 +65,93 @@
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
- * }
- */
-
- /* 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 ) {
+ /*
+ * 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;
+ }
+
+ /*
+ * 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 @@
errtxt = "Bad search filter";
}
log_search_access( pb, base, scope, "???", errtxt );
- send_ldap_result( pb, err, NULL, errtxt, 0, NULL );
- goto free_and_return;
- }
-
- /* attributes */
- attrs = NULL;
- if ( ber_scanf( ber, "{v}}", &attrs ) == LBER_ERROR ) {
+ send_ldap_result( pb, err, NULL, errtxt, 0, NULL );
+ goto free_and_return;
+ }
+
+ /* 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 @@
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)
{
- charray_add(&attrs, slapi_attr_syntax_normalize("aci"));
- break;
+ 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++ )
+ {
+ 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;
+ }
+
+ 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;
+
+ 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 );
}
- if ( attrs != NULL ) {
- 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;
-
- 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 );
- }
-
- /*
- * 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 @@
}
}
- 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 @@
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 @@
/* 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)
Index: slapi-plugin.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/slapi-plugin.h,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- slapi-plugin.h 4 Jun 2008 22:22:55 -0000 1.22
+++ slapi-plugin.h 27 Jun 2008 19:28:21 -0000 1.23
@@ -72,6 +72,9 @@
#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 @@
#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
Index: slapi-private.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/slapi-private.h,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- slapi-private.h 10 Jun 2008 18:50:07 -0000 1.23
+++ slapi-private.h 27 Jun 2008 19:28:21 -0000 1.24
@@ -574,6 +574,7 @@
char **search_attrs;
int search_attrsonly;
int search_is_and;
+ char **search_gerattrs;
} p_search;
struct abandon_parameters
@@ -726,6 +727,11 @@
/* 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 @@
*/
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 @@
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);