From 20d1e7c8e9280e2175ca843f60a50addc096f134 Mon Sep 17 00:00:00 2001 From: Noriko Hosoi Date: Tue, 14 Sep 2010 18:05:56 -0700 Subject: Bug 625014 - SubTree Renames: ModRDN operation fails and the server hangs if the entry is moved to "under" the same DN. https://bugzilla.redhat.com/show_bug.cgi?id=625014 Description: adding a check if the newsuperior is the entry itself or its descendent. If it is, modrdn returns LDAP_UNWILLING_TO_PERFORM. --- ldap/servers/slapd/modrdn.c | 48 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/ldap/servers/slapd/modrdn.c b/ldap/servers/slapd/modrdn.c index 4cca3c97..e8084c22 100644 --- a/ldap/servers/slapd/modrdn.c +++ b/ldap/servers/slapd/modrdn.c @@ -79,6 +79,11 @@ do_modrdn( Slapi_PBlock *pb ) int err = 0, deloldrdn = 0; ber_len_t len = 0; size_t dnlen = 0; + char *newdn = NULL; + char *parent = NULL; + Slapi_DN sdn = {0}; + Slapi_DN snewdn = {0}; + Slapi_DN snewsuperior = {0}; LDAPDebug( LDAP_DEBUG_TRACE, "do_modrdn\n", 0, 0, 0 ); @@ -220,6 +225,38 @@ do_modrdn( Slapi_PBlock *pb ) } } + /* + * If newsuperior is myself or my descendent, the modrdn should fail. + * Note: need to check the case newrdn is given, and newsuperior + * uses the newrdn, as well. + */ + /* Both newrdn and dn are already normalized. */ + parent = slapi_dn_parent(dn); + newdn = slapi_ch_smprintf("%s,%s", newrdn, parent); + slapi_sdn_set_dn_byref(&sdn, dn); + slapi_sdn_set_dn_byref(&snewdn, newdn); + slapi_sdn_set_dn_byref(&snewsuperior, newsuperior); + if (0 == slapi_sdn_compare(&sdn, &snewsuperior) || + 0 == slapi_sdn_compare(&snewdn, &snewsuperior)) { + op_shared_log_error_access(pb, "MODRDN", rawnewsuperior, + "new superior is identical to the entry dn"); + send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, + "new superior is identical to the entry dn", 0, NULL); + goto free_and_return; + } + if (slapi_sdn_issuffix(&snewsuperior, &sdn) || + slapi_sdn_issuffix(&snewsuperior, &snewdn)) { + /* E.g., + * newsuperior: ou=sub,ou=people,dc=example,dc=com + * dn: ou=people,dc=example,dc=com + */ + op_shared_log_error_access(pb, "MODRDN", rawnewsuperior, + "new superior is descendent of the entry"); + send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, + "new superior is descendent of the entry", 0, NULL); + goto free_and_return; + } + /* * in LDAPv3 there can be optional control extensions on * the end of an LDAPMessage. we need to read them in and @@ -242,12 +279,19 @@ do_modrdn( Slapi_PBlock *pb ) slapi_pblock_set( pb, SLAPI_MODRDN_DELOLDRDN, &deloldrdn ); op_shared_rename(pb, 1 /* pass in ownership of string arguments */ ); - return; + goto ok_return; free_and_return: slapi_ch_free_string( &dn ); slapi_ch_free_string( &newrdn ); slapi_ch_free_string( &newsuperior ); +ok_return: + slapi_sdn_done(&sdn); + slapi_sdn_done(&snewdn); + slapi_sdn_done(&snewsuperior); + slapi_ch_free_string(&parent); + slapi_ch_free_string(&newdn); + return; } @@ -385,7 +429,7 @@ op_shared_rename(Slapi_PBlock *pb, int passin_args) char **rdns; int deloldrdn; Slapi_Backend *be = NULL; - Slapi_DN sdn; + Slapi_DN sdn = {0}; Slapi_Mods smods; char dnbuf[BUFSIZ]; char newrdnbuf[BUFSIZ]; -- cgit