andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone

Blame SOURCES/0053-Ticket-47525-Crash-if-setting-invalid-plugin-config-.patch

f92ce9
From e47e64776f32a0bb593d1b9b3441e080f87f36f4 Mon Sep 17 00:00:00 2001
f92ce9
From: Mark Reynolds <mreynolds@redhat.com>
f92ce9
Date: Wed, 3 Dec 2014 16:47:59 -0500
f92ce9
Subject: [PATCH 53/53] Ticket 47525 - Crash if setting invalid plugin config
f92ce9
 area for MemberOf Plugin
f92ce9
f92ce9
Bug Description:  Setting the nsslapd-pluginconfigarea to an entry that
f92ce9
                  does not have the required config attributes causes a
f92ce9
                  crash.
f92ce9
f92ce9
Fix Description:  The plugin entry was being accidentally freed instead
f92ce9
                  of the config area entry.
f92ce9
f92ce9
                  The shared config area validation was being performed
f92ce9
                  in postop - this has now been moved into the preop stage.
f92ce9
f92ce9
                  Also, set the returntext when an error occurs.
f92ce9
f92ce9
https://fedorahosted.org/389/ticket/47525
f92ce9
f92ce9
Reviewed by: rmeggins(Thanks!)
f92ce9
f92ce9
(cherry picked from commit 42f935ab7406802d522f357048db1e68d729d5e5)
f92ce9
(cherry picked from commit d06b39743ef3b016ac25a242821a5dfc1ec67cb4)
f92ce9
---
f92ce9
 ldap/servers/plugins/memberof/memberof.c        |   1 -
f92ce9
 ldap/servers/plugins/memberof/memberof_config.c | 193 ++++++++++++++++--------
f92ce9
 2 files changed, 130 insertions(+), 64 deletions(-)
f92ce9
f92ce9
diff --git a/ldap/servers/plugins/memberof/memberof.c b/ldap/servers/plugins/memberof/memberof.c
f92ce9
index bfa733a..7e3e308 100644
f92ce9
--- a/ldap/servers/plugins/memberof/memberof.c
f92ce9
+++ b/ldap/servers/plugins/memberof/memberof.c
f92ce9
@@ -408,7 +408,6 @@ int memberof_postop_start(Slapi_PBlock *pb)
f92ce9
 		}
f92ce9
 	}
f92ce9
 
f92ce9
-	memberof_set_plugin_area(slapi_entry_get_sdn(config_e));
f92ce9
 	memberof_set_config_area(slapi_entry_get_sdn(config_e));
f92ce9
 	if (( rc = memberof_config( config_e, pb )) != LDAP_SUCCESS ) {
f92ce9
 		slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
f92ce9
diff --git a/ldap/servers/plugins/memberof/memberof_config.c b/ldap/servers/plugins/memberof/memberof_config.c
f92ce9
index df8ddcb..eb83bd0 100644
f92ce9
--- a/ldap/servers/plugins/memberof/memberof_config.c
f92ce9
+++ b/ldap/servers/plugins/memberof/memberof_config.c
f92ce9
@@ -342,56 +342,40 @@ memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
f92ce9
 	*returncode = LDAP_SUCCESS;
f92ce9
 
f92ce9
 	/*
f92ce9
-	 * Apply the config settings from the shared config entry
f92ce9
+	 * Check if this is a shared config entry
f92ce9
 	 */
f92ce9
 	sharedcfg = slapi_entry_attr_get_charptr(e, SLAPI_PLUGIN_SHARED_CONFIG_AREA);
f92ce9
 	if(sharedcfg){
f92ce9
-		int rc = 0;
f92ce9
-
f92ce9
-		rc = slapi_dn_syntax_check(pb, sharedcfg, 1);
f92ce9
-		if (rc) { /* syntax check failed */
f92ce9
-			slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,"memberof_apply_config: "
f92ce9
-					"%s does not contain a valid DN (%s)\n",
f92ce9
-					SLAPI_PLUGIN_SHARED_CONFIG_AREA, sharedcfg);
f92ce9
-			*returncode = LDAP_INVALID_DN_SYNTAX;
f92ce9
-			goto done;
f92ce9
-		}
f92ce9
 		if((config_sdn = slapi_sdn_new_dn_byval(sharedcfg))){
f92ce9
 			slapi_search_internal_get_entry(config_sdn, NULL, &config_entry, memberof_get_plugin_id());
f92ce9
 			if(config_entry){
f92ce9
-				char errtext[SLAPI_DSE_RETURNTEXT_SIZE];
f92ce9
-				int err = 0;
f92ce9
-				/*
f92ce9
-				 * If we got here, we are updating the shared config area, so we need to
f92ce9
-				 * validate and apply the settings from that config area.
f92ce9
-				 */
f92ce9
-				if ( SLAPI_DSE_CALLBACK_ERROR == memberof_validate_config (pb, NULL, config_entry, &err, errtext,0))
f92ce9
-				{
f92ce9
-					slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
f92ce9
-									"%s", errtext);
f92ce9
-					*returncode = LDAP_UNWILLING_TO_PERFORM;
f92ce9
-					goto done;
f92ce9
-
f92ce9
-				}
f92ce9
+				/* Set the entry to be the shared config entry.  Validation was done in preop */
f92ce9
 				e = config_entry;
f92ce9
 			} else {
f92ce9
-				/* this should of been checked in preop validation */
f92ce9
-				slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM, "memberof_apply_config: "
f92ce9
-						"Failed to locate shared config entry (%s)\n",sharedcfg);
f92ce9
+				/* This should of been checked in preop validation */
f92ce9
+				PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
f92ce9
+					"memberof_apply_config: Failed to locate shared config entry (%s)",
f92ce9
+					sharedcfg);
f92ce9
+				slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,"%s\n",returntext);
f92ce9
 				*returncode = LDAP_UNWILLING_TO_PERFORM;
f92ce9
 				goto done;
f92ce9
 			}
f92ce9
 		}
f92ce9
 	}
f92ce9
 
f92ce9
+	/*
f92ce9
+	 * Apply the config settings
f92ce9
+	 */
f92ce9
 	groupattrs = slapi_entry_attr_get_charray(e, MEMBEROF_GROUP_ATTR);
f92ce9
 	memberof_attr = slapi_entry_attr_get_charptr(e, MEMBEROF_ATTR);
f92ce9
 	allBackends = slapi_entry_attr_get_charptr(e, MEMBEROF_BACKEND_ATTR);
f92ce9
 	entryScope = slapi_entry_attr_get_charptr(e, MEMBEROF_ENTRY_SCOPE_ATTR);
f92ce9
         entryScopeExcludeSubtree = slapi_entry_attr_get_charptr(e, MEMBEROF_ENTRY_SCOPE_EXCLUDE_SUBTREE);
f92ce9
 
f92ce9
-	/* We want to be sure we don't change the config in the middle of
f92ce9
-	 * a memberOf operation, so we obtain an exclusive lock here */
f92ce9
+	/*
f92ce9
+	 * We want to be sure we don't change the config in the middle of
f92ce9
+	 * a memberOf operation, so we obtain an exclusive lock here
f92ce9
+	 */
f92ce9
 	memberof_wlock_config();
f92ce9
 
f92ce9
 	if (groupattrs)
f92ce9
@@ -402,8 +386,10 @@ memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
f92ce9
 		theConfig.groupattrs = groupattrs;
f92ce9
 		groupattrs = NULL; /* config now owns memory */
f92ce9
 
f92ce9
-		/* We allocate a list of Slapi_Attr using the groupattrs for
f92ce9
-		 * convenience in our memberOf comparison functions */
f92ce9
+		/*
f92ce9
+		 * We allocate a list of Slapi_Attr using the groupattrs for
f92ce9
+		 * convenience in our memberOf comparison functions
f92ce9
+		 */
f92ce9
 		for (i = 0; theConfig.group_slapiattrs && theConfig.group_slapiattrs[i]; i++)
f92ce9
 		{
f92ce9
 			slapi_attr_free(&theConfig.group_slapiattrs[i]);
f92ce9
@@ -412,8 +398,10 @@ memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
f92ce9
 		/* Count the number of groupattrs. */
f92ce9
 		for (num_groupattrs = 0; theConfig.groupattrs && theConfig.groupattrs[num_groupattrs]; num_groupattrs++)
f92ce9
 		{
f92ce9
-			/* Add up the total length of all attribute names.  We need
f92ce9
-			 * to know this for building the group check filter later. */
f92ce9
+			/*
f92ce9
+			 * Add up the total length of all attribute names.  We need
f92ce9
+			 * to know this for building the group check filter later.
f92ce9
+			 */
f92ce9
 			groupattr_name_len += strlen(theConfig.groupattrs[num_groupattrs]);
f92ce9
 		}
f92ce9
 
f92ce9
@@ -434,8 +422,7 @@ memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
f92ce9
 		/* Terminate the list. */
f92ce9
 		theConfig.group_slapiattrs[i] = NULL;
f92ce9
 
f92ce9
-		/* The filter is based off of the groupattr, so we
f92ce9
-		 * update it here too. */
f92ce9
+		/* The filter is based off of the groupattr, so we update it here too. */
f92ce9
 		slapi_filter_free(theConfig.group_filter, 1);
f92ce9
 
f92ce9
 		if (num_groupattrs > 1)
f92ce9
@@ -463,11 +450,13 @@ memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
f92ce9
 			filter_str = slapi_ch_smprintf("(%s=*)", theConfig.groupattrs[0]);
f92ce9
 		}
f92ce9
 
f92ce9
-		/* Log an error if we were unable to build the group filter for some
f92ce9
+		/*
f92ce9
+		 * Log an error if we were unable to build the group filter for some
f92ce9
 		 * reason.  If this happens, the memberOf plugin will not be able to
f92ce9
 		 * check if an entry is a group, causing it to not catch changes.  This
f92ce9
 		 * shouldn't happen, but there may be some garbage configuration that
f92ce9
-		 * could trigger this. */
f92ce9
+		 * could trigger this.
f92ce9
+		 */
f92ce9
 		if ((theConfig.group_filter = slapi_str2filter(filter_str)) == NULL)
f92ce9
 		{
f92ce9
 			slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
f92ce9
@@ -547,13 +536,10 @@ memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
f92ce9
 	memberof_unlock_config();
f92ce9
 
f92ce9
 done:
f92ce9
-	slapi_ch_free_string(&sharedcfg);
f92ce9
 	slapi_sdn_free(&config_sdn);
f92ce9
-	if(config_entry){
f92ce9
-		/* we switched the entry pointer to the shared config entry - which needs to be freed */
f92ce9
-		slapi_entry_free(e);
f92ce9
-	}
f92ce9
+	slapi_entry_free(config_entry);
f92ce9
 	slapi_ch_array_free(groupattrs);
f92ce9
+	slapi_ch_free_string(&sharedcfg);
f92ce9
 	slapi_ch_free_string(&memberof_attr);
f92ce9
 	slapi_ch_free_string(&allBackends);
f92ce9
 
f92ce9
@@ -745,6 +731,7 @@ memberof_config_get_entry_scope_exclude_subtree()
f92ce9
 
f92ce9
 	return entry_exclude_subtree;
f92ce9
 }
f92ce9
+
f92ce9
 /*
f92ce9
  * Check if we are modifying the config, or changing the shared config entry
f92ce9
  */
f92ce9
@@ -753,53 +740,133 @@ memberof_shared_config_validate(Slapi_PBlock *pb)
f92ce9
 {
f92ce9
 	Slapi_Entry *e = 0;
f92ce9
 	Slapi_Entry *resulting_e = 0;
f92ce9
-	Slapi_DN *sdn = 0;
f92ce9
+	Slapi_Entry *config_entry = NULL;
f92ce9
+	Slapi_DN *sdn = NULL;
f92ce9
+	Slapi_DN *config_sdn = NULL;
f92ce9
 	Slapi_Mods *smods = 0;
f92ce9
+	Slapi_Mod *smod = NULL, *nextmod = NULL;
f92ce9
 	LDAPMod **mods = NULL;
f92ce9
 	char returntext[SLAPI_DSE_RETURNTEXT_SIZE];
f92ce9
+	char *configarea_dn = NULL;
f92ce9
 	int ret = SLAPI_PLUGIN_SUCCESS;
f92ce9
 
f92ce9
 	slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn;;
f92ce9
 
f92ce9
-   	if (slapi_sdn_issuffix(sdn, memberof_get_config_area()) &&
f92ce9
-   	    slapi_sdn_compare(sdn, memberof_get_config_area()) == 0)
f92ce9
-   	{
f92ce9
-   		/*
f92ce9
-   		 * This is the shared config entry.  Apply the mods and set/validate
f92ce9
-   		 * the config
f92ce9
-   		 */
f92ce9
-		int result = 0;
f92ce9
-
f92ce9
+	if (slapi_sdn_compare(sdn, memberof_get_plugin_area()) == 0 ||
f92ce9
+	    slapi_sdn_compare(sdn, memberof_get_config_area()) == 0)
f92ce9
+	{
f92ce9
 		slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &e);
f92ce9
 		if(e){
f92ce9
+			/*
f92ce9
+			 * Create a copy of the entry and apply the
f92ce9
+			 * mods to create the resulting entry.
f92ce9
+			 */
f92ce9
 			slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods;;
f92ce9
 			smods = slapi_mods_new();
f92ce9
 			slapi_mods_init_byref(smods, mods);
f92ce9
-
f92ce9
-			/* Create a copy of the entry and apply the
f92ce9
-			 * mods to create the resulting entry. */
f92ce9
 			resulting_e = slapi_entry_dup(e);
f92ce9
 			if (mods && (slapi_entry_apply_mods(resulting_e, mods) != LDAP_SUCCESS)) {
f92ce9
 				/* we don't care about this, the update is invalid and will be caught later */
f92ce9
 				goto bail;
f92ce9
 			}
f92ce9
 
f92ce9
-			if ( SLAPI_DSE_CALLBACK_ERROR == memberof_validate_config (pb, NULL, resulting_e, &ret, returntext,0)) {
f92ce9
-				slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
f92ce9
-								"%s", returntext);
f92ce9
-				ret = LDAP_UNWILLING_TO_PERFORM;
f92ce9
+			if (slapi_sdn_compare(sdn, memberof_get_plugin_area())){
f92ce9
+				/*
f92ce9
+				 * This entry is a plugin config area entry, validate it.
f92ce9
+				 */
f92ce9
+				if( SLAPI_DSE_CALLBACK_ERROR == memberof_validate_config (pb, NULL, resulting_e, &ret, returntext,0)) {
f92ce9
+					ret = LDAP_UNWILLING_TO_PERFORM;
f92ce9
+				}
f92ce9
+			} else {
f92ce9
+				/*
f92ce9
+				 * This is the memberOf plugin entry, check if we are adding/replacing the
f92ce9
+				 * plugin config area.
f92ce9
+				 */
f92ce9
+				nextmod = slapi_mod_new();
f92ce9
+				for (smod = slapi_mods_get_first_smod(smods, nextmod);
f92ce9
+					 smod != NULL;
f92ce9
+					 smod = slapi_mods_get_next_smod(smods, nextmod) )
f92ce9
+				{
f92ce9
+					if ( PL_strcasecmp(SLAPI_PLUGIN_SHARED_CONFIG_AREA, slapi_mod_get_type(smod)) == 0 )
f92ce9
+					{
f92ce9
+						/*
f92ce9
+						 * Okay, we are modifying the plugin config area, we only care about
f92ce9
+						 * adds and replaces.
f92ce9
+						 */
f92ce9
+						if(SLAPI_IS_MOD_REPLACE(slapi_mod_get_operation(smod)) ||
f92ce9
+						   SLAPI_IS_MOD_ADD(slapi_mod_get_operation(smod)))
f92ce9
+						{
f92ce9
+						    struct berval *bv = NULL;
f92ce9
+						    int rc = 0;
f92ce9
+
f92ce9
+							bv = slapi_mod_get_first_value(smod);
f92ce9
+							configarea_dn = slapi_ch_strdup(bv->bv_val);
f92ce9
+							if(configarea_dn){
f92ce9
+								/* Check the DN syntax */
f92ce9
+								rc = slapi_dn_syntax_check(pb, configarea_dn, 1);
f92ce9
+								if (rc) { /* syntax check failed */
f92ce9
+									PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
f92ce9
+										"%s does not contain a valid DN (%s)",
f92ce9
+										SLAPI_PLUGIN_SHARED_CONFIG_AREA, configarea_dn);
f92ce9
+									ret = LDAP_UNWILLING_TO_PERFORM;
f92ce9
+									goto bail;
f92ce9
+								}
f92ce9
+
f92ce9
+								/* Check if the plugin config area entry exists */
f92ce9
+								if((config_sdn = slapi_sdn_new_dn_byval(configarea_dn))){
f92ce9
+									rc = slapi_search_internal_get_entry(config_sdn, NULL, &config_entry,
f92ce9
+										memberof_get_plugin_id());
f92ce9
+									if(config_entry){
f92ce9
+										int err = 0;
f92ce9
+										/*
f92ce9
+										 * Validate the settings from the new config area.
f92ce9
+										 */
f92ce9
+										if ( memberof_validate_config(pb, NULL, config_entry, &err, returntext,0)
f92ce9
+											 == SLAPI_DSE_CALLBACK_ERROR )
f92ce9
+										{
f92ce9
+											ret = LDAP_UNWILLING_TO_PERFORM;
f92ce9
+											goto bail;
f92ce9
+
f92ce9
+										}
f92ce9
+									} else {
f92ce9
+										/* The config area does not exist */
f92ce9
+										PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
f92ce9
+											"Unable to locate shared config entry (%s) error %d",
f92ce9
+											slapi_sdn_get_dn(memberof_get_config_area()), rc);
f92ce9
+										ret = LDAP_UNWILLING_TO_PERFORM;
f92ce9
+										goto bail;
f92ce9
+									}
f92ce9
+								}
f92ce9
+							}
f92ce9
+							slapi_ch_free_string(&configarea_dn);
f92ce9
+							slapi_sdn_free(&config_sdn);
f92ce9
+							slapi_entry_free(config_entry);
f92ce9
+						}
f92ce9
+					}
f92ce9
+				}
f92ce9
 			}
f92ce9
 		} else {
f92ce9
-			slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM, "memberof_shared_config_validate: "
f92ce9
-											"Unable to locate shared config entry (%s) error %d\n",
f92ce9
-											slapi_sdn_get_dn(memberof_get_config_area()), result);
f92ce9
+			PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,"Unable to locate shared config entry (%s)",
f92ce9
+				slapi_sdn_get_dn(memberof_get_config_area()));
f92ce9
 			ret = LDAP_UNWILLING_TO_PERFORM;
f92ce9
 		}
f92ce9
    	}
f92ce9
 
f92ce9
 bail:
f92ce9
+
f92ce9
+	if (ret){
f92ce9
+		slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ret;;
f92ce9
+		slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, returntext);
f92ce9
+		slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM, "memberof_shared_config_validate: %s/n",
f92ce9
+			returntext);
f92ce9
+	}
f92ce9
+	slapi_sdn_free(&config_sdn);
f92ce9
+	if(nextmod)
f92ce9
+		slapi_mod_free(&nextmod);
f92ce9
 	slapi_mods_free(&smods);
f92ce9
 	slapi_entry_free(resulting_e);
f92ce9
+	slapi_entry_free(config_entry);
f92ce9
+	slapi_ch_free_string(&configarea_dn);
f92ce9
 
f92ce9
 	return ret;
f92ce9
 }
f92ce9
-- 
f92ce9
1.9.3
f92ce9