Blob Blame History Raw
From 77b673974892eaa1f026687f6cf683372cc45c8c Mon Sep 17 00:00:00 2001
From: Noriko Hosoi <nhosoi@totoro.usersys.redhat.com>
Date: Fri, 21 Sep 2012 12:35:18 -0700
Subject: [PATCH 2/3] Trac Ticket #340 - Change on SLAPI_MODRDN_NEWSUPERIOR is not
       evaluated in acl

https://fedorahosted.org/389/ticket/340

Bug Description: When modrdn operation was executed, only newrdn
change was passed to the acl plugin.  Also, the change was used
only for the acl search, but not for the acl target in the items
in the acl cache.

Fix Description: This patch also passes the newsuperior update
to the acl plugin.  And the modrdn updates are applied to the
acl target in the acl cache.
(cherry picked from commit 5beb93d42efb807838c09c5fab898876876f8d09)
1.2.10 - cherry-picked from 7399cbd53d6289df592d3414a84972eacb4dc97d
- had to fix a couple of conflicts in the acl code
---
 ldap/servers/plugins/acl/acl.c      |   77 ++++++++++++++++++++++------------
 ldap/servers/plugins/acl/acl.h      |    5 +-
 ldap/servers/plugins/acl/aclgroup.c |    2 +-
 ldap/servers/plugins/acl/acllist.c  |   48 +++++++++++++---------
 ldap/servers/slapd/dn.c             |    2 +-
 ldap/servers/slapd/plugin_acl.c     |   35 ++++++++++++----
 6 files changed, 110 insertions(+), 59 deletions(-)

diff --git a/ldap/servers/plugins/acl/acl.c b/ldap/servers/plugins/acl/acl.c
index 5a7b446..e17a827 100644
--- a/ldap/servers/plugins/acl/acl.c
+++ b/ldap/servers/plugins/acl/acl.c
@@ -170,9 +170,9 @@ acl_access_allowed_modrdn(
  * Test if have access to make the first rdn of dn in entry e.
 */
  
-static int check_rdn_access( Slapi_PBlock *pb, Slapi_Entry *e, const char *dn,
-						int access) {
-	
+static int
+check_rdn_access( Slapi_PBlock *pb, Slapi_Entry *e, const char *dn, int access)
+{
 	char **dns;
 	char **rdns;
 	int retCode = LDAP_INSUFFICIENT_ACCESS;
@@ -659,7 +659,8 @@ cleanup_and_ret:
 	
 }
 
-static void print_access_control_summary( char *source, int ret_val, char *clientDn,
+static void
+print_access_control_summary( char *source, int ret_val, char *clientDn,
 									struct	acl_pblock	*aclpb,
 									char *right,
 									char *attr,
@@ -1533,11 +1534,12 @@ acl_check_mods(
 *
 **************************************************************************/
 extern void
-acl_modified (Slapi_PBlock *pb, int optype, char *n_dn, void *change)
+acl_modified (Slapi_PBlock *pb, int optype, Slapi_DN *e_sdn, void *change)
 {
 	struct  berval	**bvalue;
 	char			**value;
 	int				rv=0;		/* returned value */
+	const char*     n_dn;
 	char*          	new_RDN;
 	char*          	parent_DN;
 	char*          	new_DN;
@@ -1547,10 +1549,12 @@ acl_modified (Slapi_PBlock *pb, int optype, char *n_dn, void *change)
 	Slapi_Attr 		*attr = NULL;
 	Slapi_Entry		*e = NULL;
 	char			ebuf [ BUFSIZ];
-	Slapi_DN		*e_sdn;
 	aclUserGroup	*ugroup = NULL;
 	
-	e_sdn = slapi_sdn_new_normdn_byval ( n_dn );
+	if (NULL == e_sdn) {
+		return;
+	}
+	n_dn = slapi_sdn_get_dn(e_sdn);
 	/* Before we proceed, Let's first check if we are changing any groups.
 	** If we are, then we need to change the signature
 	*/
@@ -1778,45 +1782,64 @@ acl_modified (Slapi_PBlock *pb, int optype, char *n_dn, void *change)
 		}
 
 		break;
-	   }/* case op is modify*/
+	    }/* case op is modify*/
 
-	   case SLAPI_OPERATION_MODRDN:
-
-		new_RDN = (char*) change;
-		slapi_log_error (SLAPI_LOG_ACL, plugin_name, 
-			   "acl_modified (MODRDN %s => \"%s\"\n", 
-			   ACL_ESCAPE_STRING_WITH_PUNCTUATION (n_dn, ebuf), new_RDN);
+	    case SLAPI_OPERATION_MODRDN:
+	    {
+		char **rdn_parent;
+		rdn_parent = (char **)change;
+		new_RDN = rdn_parent[0];
+		parent_DN = rdn_parent[1];
 
 		/* compute new_DN: */
-		parent_DN = slapi_dn_parent (n_dn);
-		if (parent_DN == NULL) {
-			new_DN = new_RDN;
+		if (NULL == parent_DN) {
+			parent_DN = slapi_dn_parent(n_dn);
+		}
+		if (NULL == parent_DN) {
+			if (NULL == new_RDN) {
+				slapi_log_error (SLAPI_LOG_ACL, plugin_name, 
+				                 "acl_modified (MODRDN %s => \"no change\"\n", 
+				                 n_dn);
+				break;
+			} else {
+				new_DN = new_RDN;
+			}
 		} else {
-			new_DN = slapi_create_dn_string("%s,%s", new_RDN, parent_DN);
+			if (NULL == new_RDN) {
+				Slapi_RDN *rdn= slapi_rdn_new();
+				slapi_sdn_get_rdn(e_sdn, rdn);
+				new_DN = slapi_create_dn_string("%s,%s", slapi_rdn_get_rdn(rdn),
+				                                parent_DN);
+				slapi_rdn_free(&rdn);
+			} else {
+				new_DN = slapi_create_dn_string("%s,%s", new_RDN, parent_DN);
+			}
 		}
+		slapi_log_error (SLAPI_LOG_ACL, plugin_name, 
+		                 "acl_modified (MODRDN %s => \"%s\"\n", n_dn, new_RDN);
 
 		/* Change the acls */
-		acllist_acicache_WRITE_LOCK();		
+		acllist_acicache_WRITE_LOCK();
 		/* acllist_moddn_aci_needsLock expects normalized new_DN, 
 		 * which is no need to be case-ignored */
 		acllist_moddn_aci_needsLock ( e_sdn, new_DN );
 		acllist_acicache_WRITE_UNLOCK();
 
 		/* deallocat the parent_DN */
-		if (parent_DN != NULL)  {
-			slapi_ch_free ( (void **) &new_DN );
-			slapi_ch_free ( (void **) &parent_DN );
+		if (parent_DN != NULL) {
+			slapi_ch_free_string(&new_DN);
+			if (parent_DN != rdn_parent[1]) {
+				slapi_ch_free_string(&parent_DN);
+			}
 		}
 		break;
-
-	   default:
+	    } /* case op is modrdn */
+	    default:
 		/* print ERROR */
 		break;
 	} /*optype switch */
-		
-	slapi_sdn_free ( &e_sdn );	
-
 }
+
 /***************************************************************************
 *
 * acl__scan_for_acis
diff --git a/ldap/servers/plugins/acl/acl.h b/ldap/servers/plugins/acl/acl.h
index 4fa3e3f..28c38e7 100644
--- a/ldap/servers/plugins/acl/acl.h
+++ b/ldap/servers/plugins/acl/acl.h
@@ -796,7 +796,8 @@ int  		acl_read_access_allowed_on_attr ( Slapi_PBlock *pb, Slapi_Entry *e, char
                                   struct berval *val, int access);
 void 		acl_set_acllist (Slapi_PBlock *pb, int scope, char *base);
 void 		acl_gen_err_msg(int access, char *edn, char *attr, char **errbuf);
-void 		acl_modified ( Slapi_PBlock *pb, int optype, char *dn, void *change);
+void 		acl_modified (Slapi_PBlock *pb, int optype, Slapi_DN *e_sdn, void *change);
+
 int 		acl_access_allowed_disjoint_resource( Slapi_PBlock *pb, Slapi_Entry *e,
 					char *attr, struct berval *val, int access );
 int 		acl_access_allowed_main ( Slapi_PBlock *pb, Slapi_Entry *e, char **attrs, 
@@ -866,7 +867,7 @@ void		acllist_print_tree ( Avlnode *root, int *depth, char *start, char *side);
 AciContainer *acllist_get_aciContainer_new ( );
 void 		acllist_done_aciContainer (  AciContainer *);
 
-aclUserGroup* aclg_find_userGroup (char *n_dn);
+aclUserGroup* aclg_find_userGroup (const char *n_dn);
 void 		aclg_regen_ugroup_signature( aclUserGroup *ugroup);
 void		aclg_markUgroupForRemoval ( aclUserGroup *u_group );
 void		aclg_reader_incr_ugroup_refcnt(aclUserGroup* u_group);
diff --git a/ldap/servers/plugins/acl/aclgroup.c b/ldap/servers/plugins/acl/aclgroup.c
index c694293..2231304 100644
--- a/ldap/servers/plugins/acl/aclgroup.c
+++ b/ldap/servers/plugins/acl/aclgroup.c
@@ -213,7 +213,7 @@ aclg_reset_userGroup ( struct acl_pblock *aclpb )
 */
 
 aclUserGroup*
-aclg_find_userGroup(char *n_dn)
+aclg_find_userGroup(const char *n_dn)
 {
 	aclUserGroup		*u_group = NULL;	
 	int			i;
diff --git a/ldap/servers/plugins/acl/acllist.c b/ldap/servers/plugins/acl/acllist.c
index 9b5363a..e8198af 100644
--- a/ldap/servers/plugins/acl/acllist.c
+++ b/ldap/servers/plugins/acl/acllist.c
@@ -600,7 +600,6 @@ void
 acllist_init_scan (Slapi_PBlock *pb, int scope, const char *base)
 {
 	Acl_PBlock			*aclpb;
-	int					i;
 	AciContainer		*root;
 	char				*basedn = NULL;
 	int					index;
@@ -671,11 +670,6 @@ acllist_init_scan (Slapi_PBlock *pb, int scope, const char *base)
 		aclpb->aclpb_state &= ~ACLPB_SEARCH_BASED_ON_LIST ;
 
 	acllist_acicache_READ_UNLOCK();
-
-	i = 0;
-	while ( i < aclpb_max_selected_acls && aclpb->aclpb_base_handles_index[i]  != -1 ) {
-		i++;
-	}
 }
 
 /*
@@ -893,34 +887,50 @@ acllist_acicache_WRITE_LOCK( )
 int
 acllist_moddn_aci_needsLock ( Slapi_DN *oldsdn, char *newdn )
 {
-
-
 	AciContainer		*aciListHead;
 	AciContainer		*head;
+	aci_t *acip;
+	const char *oldndn;
 
 	/* first get the container */
 
 	aciListHead =   acllist_get_aciContainer_new ( );
 	slapi_sdn_free(&aciListHead->acic_sdn);
-    aciListHead->acic_sdn = oldsdn;
-
+	aciListHead->acic_sdn = oldsdn;
 
 	if ( NULL == (head = (AciContainer *) avl_find( acllistRoot, aciListHead,
-									(IFP) __acllist_aciContainer_node_cmp ) ) ) {
+	     (IFP) __acllist_aciContainer_node_cmp ) ) ) {
 
 		slapi_log_error ( SLAPI_PLUGIN_ACL, plugin_name,
- 						"Can't find the acl in the tree for moddn operation:olddn%s\n",
-							slapi_sdn_get_ndn ( oldsdn ));
+		         "Can't find the acl in the tree for moddn operation:olddn%s\n",
+		         slapi_sdn_get_ndn ( oldsdn ));
 		aciListHead->acic_sdn = NULL;
 		__acllist_free_aciContainer ( &aciListHead );
- 		return 1;
+		return 1;
 	}
 
-
-	/* Now set the new DN */	
-	slapi_sdn_done ( head->acic_sdn );
- 	slapi_sdn_set_normdn_byval ( head->acic_sdn, newdn );
-
+	/* Now set the new DN */
+	slapi_sdn_set_normdn_byval(head->acic_sdn, newdn);
+
+	/* If necessary, reset the target DNs, as well. */
+	oldndn = slapi_sdn_get_ndn(oldsdn);
+	for (acip = head->acic_list; acip; acip = acip->aci_next) {
+		const char *ndn = slapi_sdn_get_ndn(acip->aci_sdn);
+		char *p = PL_strstr(ndn, oldndn);
+		if (p) {
+			if (p == ndn) {
+				/* target dn is identical, replace it with new DN*/
+				slapi_sdn_set_normdn_byval(acip->aci_sdn, newdn);
+			} else {
+				/* target dn is a descendent of olddn, merge it with new DN*/
+				char *mynewdn;
+				*p = '\0';
+				mynewdn = slapi_ch_smprintf("%s%s", ndn, newdn);
+				slapi_sdn_set_normdn_passin(acip->aci_sdn, mynewdn);
+			}
+		}
+	}
+    
 	aciListHead->acic_sdn = NULL;
 	__acllist_free_aciContainer ( &aciListHead );
 
diff --git a/ldap/servers/slapd/dn.c b/ldap/servers/slapd/dn.c
index 568871f..35c0700 100644
--- a/ldap/servers/slapd/dn.c
+++ b/ldap/servers/slapd/dn.c
@@ -2037,7 +2037,7 @@ slapi_sdn_set_normdn_byval(Slapi_DN *sdn, const char *normdn)
     slapi_sdn_done(sdn);
     sdn->flag = slapi_setbit_uchar(sdn->flag, FLAG_DN);
     if(normdn == NULL) {
-        sdn->dn = slapi_ch_strdup(normdn);
+        sdn->dn = NULL;
         sdn->ndn_len = 0;
     } else {
         sdn->dn = slapi_ch_strdup(normdn);
diff --git a/ldap/servers/slapd/plugin_acl.c b/ldap/servers/slapd/plugin_acl.c
index 24dcc76..3bc3f21 100644
--- a/ldap/servers/slapd/plugin_acl.c
+++ b/ldap/servers/slapd/plugin_acl.c
@@ -134,11 +134,10 @@ int
 plugin_call_acl_mods_update ( Slapi_PBlock *pb, int optype )
 {
 	struct slapdplugin	*p;
-	char 				*dn;
 	int					rc = 0;
-   	void				*change = NULL;
-   	Slapi_Entry			*te = NULL;
-    Slapi_DN			*sdn = NULL;
+	void				*change = NULL;
+	Slapi_Entry			*te = NULL;
+	Slapi_DN			*sdn = NULL;
 	Operation			*operation;
 
 	slapi_pblock_get (pb, SLAPI_OPERATION, &operation);
@@ -146,7 +145,7 @@ plugin_call_acl_mods_update ( Slapi_PBlock *pb, int optype )
 	(void)slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn );
 
 	switch ( optype ) {
- 	  case SLAPI_OPERATION_MODIFY:
+	  case SLAPI_OPERATION_MODIFY:
 		(void)slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &change );
 		break;
 	  case SLAPI_OPERATION_ADD:
@@ -157,9 +156,28 @@ plugin_call_acl_mods_update ( Slapi_PBlock *pb, int optype )
 			sdn = slapi_entry_get_sdn(te);
 		}
 		break;
-    	  case SLAPI_OPERATION_MODRDN:
-		(void)slapi_pblock_get( pb, SLAPI_MODRDN_NEWRDN, &change );
+	  case SLAPI_OPERATION_MODRDN:
+	  {
+		void *mychange[2];
+		char *newrdn = NULL;
+		Slapi_DN *psdn = NULL;
+		char *pdn = NULL;
+
+		/* newrdn: "change" is normalized but not case-ignored */
+		/* The acl plugin expects normalized newrdn, but no need to be case-
+		 * ignored. */
+		(void)slapi_pblock_get( pb, SLAPI_MODRDN_NEWRDN, &newrdn );
+		(void)slapi_pblock_get( pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &psdn );
+		if (psdn) {
+			pdn = (char *)slapi_sdn_get_dn(psdn);
+		} else {
+			(void)slapi_pblock_get( pb, SLAPI_MODRDN_NEWSUPERIOR, &pdn );
+		}
+		mychange[0] = newrdn;
+		mychange[1] = pdn;
+		change = mychange;
 		break;
+	  }
 	}
 	
 	if (NULL == sdn) {
@@ -169,10 +187,9 @@ plugin_call_acl_mods_update ( Slapi_PBlock *pb, int optype )
 	}
 
 	/* call the global plugins first and then the backend specific */
-	dn = (char*)slapi_sdn_get_ndn(sdn); /* jcm - Had to cast away const */
 	for ( p = get_plugin_list(PLUGIN_LIST_ACL); p != NULL; p = p->plg_next ) {
 		if (plugin_invoke_plugin_sdn(p, SLAPI_PLUGIN_ACL_MODS_UPDATE, pb, sdn)){
-			rc = (*p->plg_acl_mods_update)(pb, optype, dn, change );
+			rc = (*p->plg_acl_mods_update)(pb, optype, sdn, change );
 			if ( rc != LDAP_SUCCESS ) break;
 		}
 	}
-- 
1.7.1