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