From 6e34cb6e7a45fb752d59d87c6ad2de009a54bed1 Mon Sep 17 00:00:00 2001 From: Mark Reynolds Date: Fri, 17 Sep 2021 11:30:26 -0400 Subject: [PATCH] Bump version to 2.0.8-5 Resolves: Bug 2000420 - Not able to preserve users using "ipa user-del --preserve" --- ...ailure-in-ipa-user-del-preserve-4907.patch | 296 ++++++++++++++++++ 389-ds-base.spec | 7 +- 2 files changed, 302 insertions(+), 1 deletion(-) create mode 100644 0002-Issue-4894-IPA-failure-in-ipa-user-del-preserve-4907.patch diff --git a/0002-Issue-4894-IPA-failure-in-ipa-user-del-preserve-4907.patch b/0002-Issue-4894-IPA-failure-in-ipa-user-del-preserve-4907.patch new file mode 100644 index 0000000..f274d36 --- /dev/null +++ b/0002-Issue-4894-IPA-failure-in-ipa-user-del-preserve-4907.patch @@ -0,0 +1,296 @@ +From faab51b0d14bdf7af013abdd7937f47cc0eb5cdc Mon Sep 17 00:00:00 2001 +From: Simon Pichugin +Date: Fri, 10 Sep 2021 14:17:41 -0700 +Subject: [PATCH] Issue 4894 - IPA failure in ipa user-del --preserve (#4907) + +Bug Description: Starting with 389-ds 2.0.8 on rawhide, +any call to ipa user-del --preserve fails with +This entry already exists. + +Fix Description: We should split 'dn' parameter in searchAllSubtrees +into parent and target. As one of them is used for excluding the +subtree checks and another one for searching. +Improve 'superior' processing when we don't change the parent. +Rename variables in a more sane way. + +Fixes: https://github.com/389ds/389-ds-base/issues/4894 + +Reviewed by: @Firstyear, @tbordaz, @progier389 (Thanks!) +--- + ldap/servers/plugins/uiduniq/uid.c | 78 +++++++++++++++--------------- + 1 file changed, 39 insertions(+), 39 deletions(-) + +diff --git a/ldap/servers/plugins/uiduniq/uid.c b/ldap/servers/plugins/uiduniq/uid.c +index 9924623a7..5b763b551 100644 +--- a/ldap/servers/plugins/uiduniq/uid.c ++++ b/ldap/servers/plugins/uiduniq/uid.c +@@ -770,13 +770,13 @@ search_one_berval(Slapi_DN *baseDN, const char **attrNames, const struct berval + * + * Return: + * LDAP_SUCCESS - no matches, or the attribute matches the +- * target dn. ++ * source (target) dn. + * LDAP_CONSTRAINT_VIOLATION - an entry was found that already + * contains the attribute value. + * LDAP_OPERATIONS_ERROR - a server failure. + */ + static int +-searchAllSubtrees(Slapi_DN **subtrees, Slapi_DN **exclude_subtrees, const char **attrNames, Slapi_Attr *attr, struct berval **values, const char *requiredObjectClass, Slapi_DN *dn, PRBool unique_in_all_subtrees) ++searchAllSubtrees(Slapi_DN **subtrees, Slapi_DN **exclude_subtrees, const char **attrNames, Slapi_Attr *attr, struct berval **values, const char *requiredObjectClass, Slapi_DN *destinationSDN, Slapi_DN *sourceSDN, PRBool unique_in_all_subtrees) + { + int result = LDAP_SUCCESS; + int i; +@@ -788,12 +788,12 @@ searchAllSubtrees(Slapi_DN **subtrees, Slapi_DN **exclude_subtrees, const char * + * are unique in all the monitored subtrees + */ + +- /* First check the target entry is in one of ++ /* First check the destination entry is in one of + * the monitored subtree, so adding 'values' would + * violate constraint + */ + for (i = 0; subtrees && subtrees[i]; i++) { +- if (slapi_sdn_issuffix(dn, subtrees[i])) { ++ if (slapi_sdn_issuffix(destinationSDN, subtrees[i])) { + in_a_subtree = PR_TRUE; + break; + } +@@ -808,7 +808,7 @@ searchAllSubtrees(Slapi_DN **subtrees, Slapi_DN **exclude_subtrees, const char * + if (exclude_subtrees != NULL) { + PRBool in_a_subtree = PR_FALSE; + for (i = 0; exclude_subtrees && exclude_subtrees[i]; i++) { +- if (slapi_sdn_issuffix(dn, exclude_subtrees[i])) { ++ if (slapi_sdn_issuffix(destinationSDN, exclude_subtrees[i])) { + in_a_subtree = PR_TRUE; + break; + } +@@ -820,7 +820,7 @@ searchAllSubtrees(Slapi_DN **subtrees, Slapi_DN **exclude_subtrees, const char * + + /* + * For each DN in the managed list, do uniqueness checking if +- * the target DN is a subnode in the tree. ++ * the destination (target) DN is a subnode in the tree. + */ + for (i = 0; subtrees && subtrees[i]; i++) { + Slapi_DN *sufdn = subtrees[i]; +@@ -828,8 +828,8 @@ searchAllSubtrees(Slapi_DN **subtrees, Slapi_DN **exclude_subtrees, const char * + * The DN should already be normalized, so we don't have to + * worry about that here. + */ +- if (unique_in_all_subtrees || slapi_sdn_issuffix(dn, sufdn)) { +- result = search(sufdn, attrNames, attr, values, requiredObjectClass, dn, exclude_subtrees); ++ if (unique_in_all_subtrees || slapi_sdn_issuffix(destinationSDN, sufdn)) { ++ result = search(sufdn, attrNames, attr, values, requiredObjectClass, sourceSDN, exclude_subtrees); + if (result) + break; + } +@@ -903,20 +903,20 @@ getArguments(Slapi_PBlock *pb, char **attrName, char **markerObjectClass, char * + * + * Return: + * LDAP_SUCCESS - no matches, or the attribute matches the +- * target dn. ++ * source (target) dn. + * LDAP_CONSTRAINT_VIOLATION - an entry was found that already + * contains the attribute value. + * LDAP_OPERATIONS_ERROR - a server failure. + */ + static int +-findSubtreeAndSearch(Slapi_DN *parentDN, const char **attrNames, Slapi_Attr *attr, struct berval **values, const char *requiredObjectClass, Slapi_DN *target, const char *markerObjectClass, Slapi_DN **excludes) ++findSubtreeAndSearch(Slapi_DN *destinationSDN, const char **attrNames, Slapi_Attr *attr, struct berval **values, const char *requiredObjectClass, Slapi_DN *sourceSDN, const char *markerObjectClass, Slapi_DN **excludes) + { + int result = LDAP_SUCCESS; + Slapi_PBlock *spb = NULL; + Slapi_DN *curpar = slapi_sdn_new(); + Slapi_DN *newpar = NULL; + +- slapi_sdn_get_parent(parentDN, curpar); ++ slapi_sdn_get_parent(destinationSDN, curpar); + while (slapi_sdn_get_dn(curpar) != NULL) { + if ((spb = dnHasObjectClass(curpar, markerObjectClass))) { + freePblock(spb); +@@ -925,7 +925,7 @@ findSubtreeAndSearch(Slapi_DN *parentDN, const char **attrNames, Slapi_Attr *att + * to have the attribute already. + */ + result = search(curpar, attrNames, attr, values, requiredObjectClass, +- target, excludes); ++ sourceSDN, excludes); + break; + } + newpar = slapi_sdn_new(); +@@ -964,7 +964,7 @@ preop_add(Slapi_PBlock *pb) + int err; + char *markerObjectClass = NULL; + char *requiredObjectClass = NULL; +- Slapi_DN *sdn = NULL; ++ Slapi_DN *targetSDN = NULL; + int isupdatedn; + Slapi_Entry *e; + Slapi_Attr *attr; +@@ -998,16 +998,16 @@ preop_add(Slapi_PBlock *pb) + attr_friendly = config->attr_friendly; + + /* +- * Get the target DN for this add operation ++ * Get the target SDN for this add operation + */ +- err = slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &sdn); ++ err = slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &targetSDN); + if (err) { + result = uid_op_error(51); + break; + } + + #ifdef DEBUG +- slapi_log_err(SLAPI_LOG_PLUGIN, plugin_name, "preop_add - ADD target=%s\n", slapi_sdn_get_dn(sdn)); ++ slapi_log_err(SLAPI_LOG_PLUGIN, plugin_name, "preop_add - ADD target=%s\n", slapi_sdn_get_dn(targetSDN)); + #endif + + /* +@@ -1040,13 +1040,13 @@ preop_add(Slapi_PBlock *pb) + */ + if (NULL != markerObjectClass) { + /* Subtree defined by location of marker object class */ +- result = findSubtreeAndSearch(sdn, attrNames, attr, NULL, +- requiredObjectClass, sdn, ++ result = findSubtreeAndSearch(targetSDN, attrNames, attr, NULL, ++ requiredObjectClass, targetSDN, + markerObjectClass, config->exclude_subtrees); + } else { + /* Subtrees listed on invocation line */ + result = searchAllSubtrees(config->subtrees, config->exclude_subtrees, attrNames, attr, NULL, +- requiredObjectClass, sdn, config->unique_in_all_subtrees); ++ requiredObjectClass, targetSDN, targetSDN, config->unique_in_all_subtrees); + } + if (result != LDAP_SUCCESS) { + break; +@@ -1120,7 +1120,7 @@ preop_modify(Slapi_PBlock *pb) + int modcount = 0; + int ii; + LDAPMod *mod; +- Slapi_DN *sdn = NULL; ++ Slapi_DN *targetSDN = NULL; + int isupdatedn; + int i = 0; + +@@ -1186,8 +1186,8 @@ preop_modify(Slapi_PBlock *pb) + break; /* no mods to check, we are done */ + } + +- /* Get the target DN */ +- err = slapi_pblock_get(pb, SLAPI_MODIFY_TARGET_SDN, &sdn); ++ /* Get the target SDN */ ++ err = slapi_pblock_get(pb, SLAPI_MODIFY_TARGET_SDN, &targetSDN); + if (err) { + result = uid_op_error(11); + break; +@@ -1197,7 +1197,7 @@ preop_modify(Slapi_PBlock *pb) + * Check if it has the required object class + */ + if (requiredObjectClass && +- !(spb = dnHasObjectClass(sdn, requiredObjectClass))) { ++ !(spb = dnHasObjectClass(targetSDN, requiredObjectClass))) { + break; + } + +@@ -1213,13 +1213,13 @@ preop_modify(Slapi_PBlock *pb) + mod = checkmods[ii]; + if (NULL != markerObjectClass) { + /* Subtree defined by location of marker object class */ +- result = findSubtreeAndSearch(sdn, attrNames, NULL, ++ result = findSubtreeAndSearch(targetSDN, attrNames, NULL, + mod->mod_bvalues, requiredObjectClass, +- sdn, markerObjectClass, config->exclude_subtrees); ++ targetSDN, markerObjectClass, config->exclude_subtrees); + } else { + /* Subtrees listed on invocation line */ + result = searchAllSubtrees(config->subtrees, config->exclude_subtrees, attrNames, NULL, +- mod->mod_bvalues, requiredObjectClass, sdn, config->unique_in_all_subtrees); ++ mod->mod_bvalues, requiredObjectClass, targetSDN, targetSDN, config->unique_in_all_subtrees); + } + } + END +@@ -1271,8 +1271,8 @@ preop_modrdn(Slapi_PBlock *pb) + int err; + char *markerObjectClass = NULL; + char *requiredObjectClass = NULL; +- Slapi_DN *sdn = NULL; +- Slapi_DN *superior; ++ Slapi_DN *sourceSDN = NULL; ++ Slapi_DN *destinationSDN; + char *rdn; + int deloldrdn = 0; + int isupdatedn; +@@ -1311,14 +1311,14 @@ preop_modrdn(Slapi_PBlock *pb) + } + + /* Get the DN of the entry being renamed */ +- err = slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_SDN, &sdn); ++ err = slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_SDN, &sourceSDN); + if (err) { + result = uid_op_error(31); + break; + } + + /* Get superior value - unimplemented in 3.0/4.0/5.0 DS */ +- err = slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &superior); ++ err = slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &destinationSDN); + if (err) { + result = uid_op_error(32); + break; +@@ -1326,11 +1326,11 @@ preop_modrdn(Slapi_PBlock *pb) + + /* + * No superior means the entry is just renamed at +- * its current level in the tree. Use the target DN for ++ * its current level in the tree. Use the source SDN for + * determining which managed tree this belongs to + */ +- if (!superior) +- superior = sdn; ++ if (!destinationSDN) ++ slapi_sdn_get_parent(sourceSDN, destinationSDN); + + /* Get the new RDN - this has the attribute values */ + err = slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &rdn); +@@ -1352,10 +1352,10 @@ preop_modrdn(Slapi_PBlock *pb) + + /* Get the entry that is being renamed so we can make a dummy copy + * of what it will look like after the rename. */ +- err = slapi_search_get_entry(&entry_pb, sdn, NULL, &e, plugin_identity); ++ err = slapi_search_get_entry(&entry_pb, sourceSDN, NULL, &e, plugin_identity); + if (err != LDAP_SUCCESS) { + result = uid_op_error(35); +- /* We want to return a no such object error if the target doesn't exist. */ ++ /* We want to return a no such object error if the source SDN doesn't exist. */ + if (err == LDAP_NO_SUCH_OBJECT) { + result = err; + } +@@ -1364,7 +1364,7 @@ preop_modrdn(Slapi_PBlock *pb) + + /* Apply the rename operation to the dummy entry. */ + /* slapi_entry_rename does not expect rdn normalized */ +- err = slapi_entry_rename(e, rdn, deloldrdn, superior); ++ err = slapi_entry_rename(e, rdn, deloldrdn, destinationSDN); + if (err != LDAP_SUCCESS) { + result = uid_op_error(36); + break; +@@ -1392,13 +1392,13 @@ preop_modrdn(Slapi_PBlock *pb) + */ + if (NULL != markerObjectClass) { + /* Subtree defined by location of marker object class */ +- result = findSubtreeAndSearch(slapi_entry_get_sdn(e), attrNames, attr, NULL, +- requiredObjectClass, superior, ++ result = findSubtreeAndSearch(destinationSDN, attrNames, attr, NULL, ++ requiredObjectClass, sourceSDN, + markerObjectClass, config->exclude_subtrees); + } else { + /* Subtrees listed on invocation line */ + result = searchAllSubtrees(config->subtrees, config->exclude_subtrees, attrNames, attr, NULL, +- requiredObjectClass, superior, config->unique_in_all_subtrees); ++ requiredObjectClass, destinationSDN, sourceSDN, config->unique_in_all_subtrees); + } + if (result != LDAP_SUCCESS) { + break; +-- +2.31.1 + diff --git a/389-ds-base.spec b/389-ds-base.spec index 83936ee..cc3a981 100644 --- a/389-ds-base.spec +++ b/389-ds-base.spec @@ -47,7 +47,7 @@ ExcludeArch: i686 Summary: 389 Directory Server (base) Name: 389-ds-base Version: 2.0.8 -Release: 4%{?dist} +Release: 5%{?dist} License: GPLv3+ and ASL 2.0 and MPLv2.0 and Boost URL: https://www.port389.org Conflicts: selinux-policy-base < 3.9.8 @@ -257,6 +257,7 @@ Source2: %{name}-devel.README Source3: https://github.com/jemalloc/%{jemalloc_name}/releases/download/%{jemalloc_ver}/%{jemalloc_name}-%{jemalloc_ver}.tar.bz2 %endif Patch01: 0001-Issue-4884-server-crashes-when-dnaInterval-attribute.patch +Patch02: 0002-Issue-4894-IPA-failure-in-ipa-user-del-preserve-4907.patch %description 389 Directory Server is an LDAPv3 compliant server. The base package includes @@ -706,6 +707,10 @@ exit 0 %endif %changelog +* Fri Sep 17 2021 Mark Reynolds - 2.0.8-5 +- Bump version to 2.0.8-5 +- Resolves: Bug 2000420 - Not able to preserve users using "ipa user-del --preserve" + * Mon Aug 30 2021 Mark Reynolds - 2.0.8-4 - Bump version to 2.0.8-4 - Resolves: Bug 1992609 - Fix specfile issue with applying patches