[Fedora-directory-commits] ldapserver/ldap/servers/slapd charray.c, 1.6, 1.7 opshared.c, 1.11, 1.12 pblock.c, 1.13, 1.14 result.c, 1.12, 1.13 schema.c, 1.14, 1.15 search.c, 1.8, 1.9 slapi-plugin.h, 1.22, 1.23 slapi-private.h, 1.23, 1.24

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/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-present_attributes



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);
 




More information about the Fedora-directory-commits mailing list