|
|
309aa9 |
From 205bce153c7db8258a8a28498cf54e7374dca588 Mon Sep 17 00:00:00 2001
|
|
|
309aa9 |
From: Thierry Bordaz <tbordaz@redhat.com>
|
|
|
309aa9 |
Date: Tue, 14 Apr 2015 16:24:44 +0200
|
|
|
309aa9 |
Subject: [PATCH] CVE-2015-1854 389ds-base: access control bypass with modrdn
|
|
|
309aa9 |
|
|
|
309aa9 |
Bug Description:
|
|
|
309aa9 |
47553 fix checks the write right access only if the RDN is
|
|
|
309aa9 |
modified. This allows to rename entries even if the
|
|
|
309aa9 |
authenticated user is not allowed of that.
|
|
|
309aa9 |
|
|
|
309aa9 |
Fix Description:
|
|
|
309aa9 |
Roll back a wrong optimization that tested the write access
|
|
|
309aa9 |
only if RDN value was changed.
|
|
|
309aa9 |
|
|
|
309aa9 |
https://fedorahosted.org/389/ticket/47553
|
|
|
309aa9 |
|
|
|
309aa9 |
Reviewed by: ?
|
|
|
309aa9 |
|
|
|
309aa9 |
Platforms tested: F17 (upstream test)
|
|
|
309aa9 |
|
|
|
309aa9 |
Flag Day: no
|
|
|
309aa9 |
|
|
|
309aa9 |
Doc impact: no
|
|
|
309aa9 |
|
|
|
309aa9 |
(cherry picked from commit 44e5c0998bdf7dcb167e8472713ff393b776e4e3)
|
|
|
309aa9 |
|
|
|
309aa9 |
Conflicts:
|
|
|
309aa9 |
dirsrvtests/tickets/ticket47553_single_aci_test.py
|
|
|
309aa9 |
---
|
|
|
309aa9 |
dirsrvtests/tickets/ticket47553_rdn_write_test.py | 132 +++++++++++++++++++++
|
|
|
309aa9 |
dirsrvtests/tickets/ticket47553_single_aci_test.py | 52 ++++++--
|
|
|
309aa9 |
ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 32 ++---
|
|
|
309aa9 |
3 files changed, 184 insertions(+), 32 deletions(-)
|
|
|
309aa9 |
create mode 100644 dirsrvtests/tickets/ticket47553_rdn_write_test.py
|
|
|
309aa9 |
|
|
|
309aa9 |
diff --git a/dirsrvtests/tickets/ticket47553_rdn_write_test.py b/dirsrvtests/tickets/ticket47553_rdn_write_test.py
|
|
|
309aa9 |
new file mode 100644
|
|
|
309aa9 |
index 0000000..f15d9b3
|
|
|
309aa9 |
--- /dev/null
|
|
|
309aa9 |
+++ b/dirsrvtests/tickets/ticket47553_rdn_write_test.py
|
|
|
309aa9 |
@@ -0,0 +1,132 @@
|
|
|
309aa9 |
+import os
|
|
|
309aa9 |
+import sys
|
|
|
309aa9 |
+import time
|
|
|
309aa9 |
+import ldap
|
|
|
309aa9 |
+import logging
|
|
|
309aa9 |
+import pytest
|
|
|
309aa9 |
+from lib389 import DirSrv, Entry, tools, tasks
|
|
|
309aa9 |
+from lib389.tools import DirSrvTools
|
|
|
309aa9 |
+from lib389._constants import *
|
|
|
309aa9 |
+from lib389.properties import *
|
|
|
309aa9 |
+from lib389.tasks import *
|
|
|
309aa9 |
+from lib389.utils import *
|
|
|
309aa9 |
+from ldap.controls.simple import GetEffectiveRightsControl
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+logging.getLogger(__name__).setLevel(logging.DEBUG)
|
|
|
309aa9 |
+log = logging.getLogger(__name__)
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+installation1_prefix = None
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+SRC_ENTRY_CN = "tuser"
|
|
|
309aa9 |
+EXT_RDN = "01"
|
|
|
309aa9 |
+DST_ENTRY_CN = SRC_ENTRY_CN + EXT_RDN
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+SRC_ENTRY_DN = "cn=%s,%s" % (SRC_ENTRY_CN, SUFFIX)
|
|
|
309aa9 |
+DST_ENTRY_DN = "cn=%s,%s" % (DST_ENTRY_CN, SUFFIX)
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+class TopologyStandalone(object):
|
|
|
309aa9 |
+ def __init__(self, standalone):
|
|
|
309aa9 |
+ standalone.open()
|
|
|
309aa9 |
+ self.standalone = standalone
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+#@pytest.fixture(scope="module")
|
|
|
309aa9 |
+def topology(request):
|
|
|
309aa9 |
+ global installation1_prefix
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+ # Creating standalone instance ...
|
|
|
309aa9 |
+ standalone = DirSrv(verbose=False)
|
|
|
309aa9 |
+ if installation1_prefix:
|
|
|
309aa9 |
+ args_instance[SER_DEPLOYED_DIR] = installation1_prefix
|
|
|
309aa9 |
+ args_instance[SER_HOST] = HOST_STANDALONE
|
|
|
309aa9 |
+ args_instance[SER_PORT] = PORT_STANDALONE
|
|
|
309aa9 |
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
|
|
|
309aa9 |
+ args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
|
|
|
309aa9 |
+ args_standalone = args_instance.copy()
|
|
|
309aa9 |
+ standalone.allocate(args_standalone)
|
|
|
309aa9 |
+ instance_standalone = standalone.exists()
|
|
|
309aa9 |
+ if instance_standalone:
|
|
|
309aa9 |
+ standalone.delete()
|
|
|
309aa9 |
+ standalone.create()
|
|
|
309aa9 |
+ standalone.open()
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+ # Clear out the tmp dir
|
|
|
309aa9 |
+ standalone.clearTmpDir(__file__)
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+ return TopologyStandalone(standalone)
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+def test_ticket47553_rdn_write_init(topology):
|
|
|
309aa9 |
+ topology.standalone.log.info("\n\n######################### Add entry tuser ######################\n")
|
|
|
309aa9 |
+ topology.standalone.add_s(Entry((SRC_ENTRY_DN, {
|
|
|
309aa9 |
+ 'objectclass': "top person".split(),
|
|
|
309aa9 |
+ 'sn': SRC_ENTRY_CN,
|
|
|
309aa9 |
+ 'cn': SRC_ENTRY_CN})))
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+def test_ticket47553_rdn_write_get_ger(topology):
|
|
|
309aa9 |
+ ANONYMOUS_DN = ""
|
|
|
309aa9 |
+ topology.standalone.log.info("\n\n######################### GER rights for anonymous ######################\n")
|
|
|
309aa9 |
+ request_ctrl = GetEffectiveRightsControl(criticality=True, authzId="dn:" + ANONYMOUS_DN)
|
|
|
309aa9 |
+ msg_id = topology.standalone.search_ext(SUFFIX, ldap.SCOPE_SUBTREE, "objectclass=*", serverctrls=[request_ctrl])
|
|
|
309aa9 |
+ rtype, rdata, rmsgid, response_ctrl = topology.standalone.result3(msg_id)
|
|
|
309aa9 |
+ value = ''
|
|
|
309aa9 |
+ for dn, attrs in rdata:
|
|
|
309aa9 |
+ topology.standalone.log.info("dn: %s" % dn)
|
|
|
309aa9 |
+ for value in attrs['entryLevelRights']:
|
|
|
309aa9 |
+ topology.standalone.log.info("############### entryLevelRights: %r" % value)
|
|
|
309aa9 |
+ assert 'n' not in value
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+def test_ticket47553_rdn_write_modrdn_anonymous(topology):
|
|
|
309aa9 |
+ ANONYMOUS_DN = ""
|
|
|
309aa9 |
+ topology.standalone.close()
|
|
|
309aa9 |
+ topology.standalone.binddn = ANONYMOUS_DN
|
|
|
309aa9 |
+ topology.standalone.open()
|
|
|
309aa9 |
+ msg_id = topology.standalone.search_ext("", ldap.SCOPE_BASE, "objectclass=*")
|
|
|
309aa9 |
+ rtype, rdata, rmsgid, response_ctrl = topology.standalone.result3(msg_id)
|
|
|
309aa9 |
+ value = ''
|
|
|
309aa9 |
+ for dn, attrs in rdata:
|
|
|
309aa9 |
+ topology.standalone.log.info("dn: %s" % dn)
|
|
|
309aa9 |
+ for attr in attrs:
|
|
|
309aa9 |
+ topology.standalone.log.info("############### %r: %r" % (attr, attrs[attr]))
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+ try:
|
|
|
309aa9 |
+ topology.standalone.rename_s(SRC_ENTRY_DN, "cn=%s" % DST_ENTRY_CN, delold=True)
|
|
|
309aa9 |
+ except Exception as e:
|
|
|
309aa9 |
+ topology.standalone.log.info("Exception (expected): %s" % type(e).__name__)
|
|
|
309aa9 |
+ isinstance(e, ldap.INSUFFICIENT_ACCESS)
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+ try:
|
|
|
309aa9 |
+ topology.standalone.getEntry(DST_ENTRY_DN, ldap.SCOPE_BASE, "objectclass=*")
|
|
|
309aa9 |
+ assert False
|
|
|
309aa9 |
+ except Exception as e:
|
|
|
309aa9 |
+ topology.standalone.log.info("The entry was not renamed (expected)")
|
|
|
309aa9 |
+ isinstance(e, ldap.NO_SUCH_OBJECT)
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+def test_ticket47553_rdn_write(topology):
|
|
|
309aa9 |
+ '''
|
|
|
309aa9 |
+ Write your testcase here...
|
|
|
309aa9 |
+ '''
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+ log.info('Test complete')
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+def test_ticket47553_rdn_write_final(topology):
|
|
|
309aa9 |
+ topology.standalone.delete()
|
|
|
309aa9 |
+ log.info('Testcase PASSED')
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+def run_isolated():
|
|
|
309aa9 |
+ global installation1_prefix
|
|
|
309aa9 |
+ installation1_prefix = '/home/tbordaz/install_master'
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+ topo = topology(True)
|
|
|
309aa9 |
+ test_ticket47553_rdn_write_init(topo)
|
|
|
309aa9 |
+ test_ticket47553_rdn_write_get_ger(topo)
|
|
|
309aa9 |
+ test_ticket47553_rdn_write(topo)
|
|
|
309aa9 |
+ test_ticket47553_rdn_write_modrdn_anonymous(topo)
|
|
|
309aa9 |
+ test_ticket47553_rdn_write_final(topo)
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+if __name__ == '__main__':
|
|
|
309aa9 |
+ run_isolated()
|
|
|
309aa9 |
+
|
|
|
309aa9 |
diff --git a/dirsrvtests/tickets/ticket47553_single_aci_test.py b/dirsrvtests/tickets/ticket47553_single_aci_test.py
|
|
|
309aa9 |
index 4be2470..0c8d7e9 100644
|
|
|
309aa9 |
--- a/dirsrvtests/tickets/ticket47553_single_aci_test.py
|
|
|
309aa9 |
+++ b/dirsrvtests/tickets/ticket47553_single_aci_test.py
|
|
|
309aa9 |
@@ -276,7 +276,27 @@ def _moddn_aci_deny_tree(topology, mod_type=None, target_from=STAGING_DN, target
|
|
|
309aa9 |
#topology.master1.modify_s(SUFFIX, mod)
|
|
|
309aa9 |
topology.master1.log.info("Add a DENY aci under %s " % PROD_EXCEPT_DN)
|
|
|
309aa9 |
topology.master1.modify_s(PROD_EXCEPT_DN, mod)
|
|
|
309aa9 |
-
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+def _write_aci_staging(topology, mod_type=None):
|
|
|
309aa9 |
+ assert mod_type is not None
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+ ACI_TARGET = "(targetattr= \"cn\")(target=\"ldap:///cn=*,%s\")" % STAGING_DN
|
|
|
309aa9 |
+ ACI_ALLOW = "(version 3.0; acl \"write staging entries\"; allow (write)"
|
|
|
309aa9 |
+ ACI_SUBJECT = " userdn = \"ldap:///%s\";)" % BIND_DN
|
|
|
309aa9 |
+ ACI_BODY = ACI_TARGET + ACI_ALLOW + ACI_SUBJECT
|
|
|
309aa9 |
+ mod = [(mod_type, 'aci', ACI_BODY)]
|
|
|
309aa9 |
+ topology.master1.modify_s(SUFFIX, mod)
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+def _write_aci_production(topology, mod_type=None):
|
|
|
309aa9 |
+ assert mod_type is not None
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+ ACI_TARGET = "(targetattr= \"cn\")(target=\"ldap:///cn=*,%s\")" % PRODUCTION_DN
|
|
|
309aa9 |
+ ACI_ALLOW = "(version 3.0; acl \"write production entries\"; allow (write)"
|
|
|
309aa9 |
+ ACI_SUBJECT = " userdn = \"ldap:///%s\";)" % BIND_DN
|
|
|
309aa9 |
+ ACI_BODY = ACI_TARGET + ACI_ALLOW + ACI_SUBJECT
|
|
|
309aa9 |
+ mod = [(mod_type, 'aci', ACI_BODY)]
|
|
|
309aa9 |
+ topology.master1.modify_s(SUFFIX, mod)
|
|
|
309aa9 |
+
|
|
|
309aa9 |
def _moddn_aci_staging_to_production(topology, mod_type=None, target_from=STAGING_DN, target_to=PRODUCTION_DN):
|
|
|
309aa9 |
assert mod_type != None
|
|
|
309aa9 |
|
|
|
309aa9 |
@@ -293,6 +313,8 @@ def _moddn_aci_staging_to_production(topology, mod_type=None, target_from=STAGIN
|
|
|
309aa9 |
ACI_BODY = ACI_TARGET_FROM + ACI_TARGET_TO + ACI_ALLOW + ACI_SUBJECT
|
|
|
309aa9 |
mod = [(mod_type, 'aci', ACI_BODY)]
|
|
|
309aa9 |
topology.master1.modify_s(SUFFIX, mod)
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+ _write_aci_staging(topology, mod_type=mod_type)
|
|
|
309aa9 |
|
|
|
309aa9 |
def _moddn_aci_from_production_to_staging(topology, mod_type=None):
|
|
|
309aa9 |
assert mod_type != None
|
|
|
309aa9 |
@@ -303,6 +325,8 @@ def _moddn_aci_from_production_to_staging(topology, mod_type=None):
|
|
|
309aa9 |
ACI_BODY = ACI_TARGET + ACI_ALLOW + ACI_SUBJECT
|
|
|
309aa9 |
mod = [(mod_type, 'aci', ACI_BODY)]
|
|
|
309aa9 |
topology.master1.modify_s(SUFFIX, mod)
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+ _write_aci_production(topology, mod_type=mod_type)
|
|
|
309aa9 |
|
|
|
309aa9 |
|
|
|
309aa9 |
def test_ticket47553_init(topology):
|
|
|
309aa9 |
@@ -347,12 +371,9 @@ def test_ticket47553_init(topology):
|
|
|
309aa9 |
'description': "production except DIT"})))
|
|
|
309aa9 |
|
|
|
309aa9 |
# enable acl error logging
|
|
|
309aa9 |
- #mod = [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', '128')]
|
|
|
309aa9 |
- #topology.master1.modify_s(DN_CONFIG, mod)
|
|
|
309aa9 |
- #topology.master2.modify_s(DN_CONFIG, mod)
|
|
|
309aa9 |
-
|
|
|
309aa9 |
-
|
|
|
309aa9 |
-
|
|
|
309aa9 |
+ mod = [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', str(128+262144))]
|
|
|
309aa9 |
+ topology.master1.modify_s(DN_CONFIG, mod)
|
|
|
309aa9 |
+ topology.master2.modify_s(DN_CONFIG, mod)
|
|
|
309aa9 |
|
|
|
309aa9 |
|
|
|
309aa9 |
# add dummy entries in the staging DIT
|
|
|
309aa9 |
@@ -883,6 +904,7 @@ def test_ticket47553_moddn_staging_prod_9(topology):
|
|
|
309aa9 |
_bind_manager(topology)
|
|
|
309aa9 |
mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
|
|
|
309aa9 |
topology.master1.modify_s(PRODUCTION_DN, mod)
|
|
|
309aa9 |
+ _write_aci_staging(topology, mod_type=ldap.MOD_ADD)
|
|
|
309aa9 |
_bind_normal(topology)
|
|
|
309aa9 |
|
|
|
309aa9 |
topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
|
|
|
309aa9 |
@@ -891,6 +913,7 @@ def test_ticket47553_moddn_staging_prod_9(topology):
|
|
|
309aa9 |
_bind_manager(topology)
|
|
|
309aa9 |
mod = [(ldap.MOD_DELETE, 'aci', ACI_BODY)]
|
|
|
309aa9 |
topology.master1.modify_s(PRODUCTION_DN, mod)
|
|
|
309aa9 |
+ _write_aci_staging(topology, mod_type=ldap.MOD_DELETE)
|
|
|
309aa9 |
_bind_normal(topology)
|
|
|
309aa9 |
|
|
|
309aa9 |
|
|
|
309aa9 |
@@ -934,6 +957,7 @@ def test_ticket47553_moddn_staging_prod_9(topology):
|
|
|
309aa9 |
_bind_manager(topology)
|
|
|
309aa9 |
mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
|
|
|
309aa9 |
topology.master1.modify_s(PRODUCTION_DN, mod)
|
|
|
309aa9 |
+ _write_aci_staging(topology, mod_type=ldap.MOD_ADD)
|
|
|
309aa9 |
_bind_normal(topology)
|
|
|
309aa9 |
|
|
|
309aa9 |
try:
|
|
|
309aa9 |
@@ -949,6 +973,7 @@ def test_ticket47553_moddn_staging_prod_9(topology):
|
|
|
309aa9 |
_bind_manager(topology)
|
|
|
309aa9 |
mod = [(ldap.MOD_DELETE, 'aci', ACI_BODY)]
|
|
|
309aa9 |
topology.master1.modify_s(PRODUCTION_DN, mod)
|
|
|
309aa9 |
+ _write_aci_staging(topology, mod_type=ldap.MOD_DELETE)
|
|
|
309aa9 |
_bind_normal(topology)
|
|
|
309aa9 |
|
|
|
309aa9 |
# Add the moddn aci that will be evaluated because of the config flag
|
|
|
309aa9 |
@@ -1009,7 +1034,12 @@ def test_ticket47553_moddn_prod_staging(topology):
|
|
|
309aa9 |
old_dn = "%s,%s" % (old_rdn, PRODUCTION_DN)
|
|
|
309aa9 |
new_rdn = old_rdn
|
|
|
309aa9 |
new_superior = STAGING_DN
|
|
|
309aa9 |
-
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+ # add the write right because we want to check the moddn
|
|
|
309aa9 |
+ _bind_manager(topology)
|
|
|
309aa9 |
+ _write_aci_production(topology, mod_type=ldap.MOD_ADD)
|
|
|
309aa9 |
+ _bind_normal(topology)
|
|
|
309aa9 |
+
|
|
|
309aa9 |
try:
|
|
|
309aa9 |
topology.master1.log.info("Try to move back MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
|
|
|
309aa9 |
topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
|
|
|
309aa9 |
@@ -1019,7 +1049,11 @@ def test_ticket47553_moddn_prod_staging(topology):
|
|
|
309aa9 |
except Exception as e:
|
|
|
309aa9 |
topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
|
|
|
309aa9 |
assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
|
|
|
309aa9 |
-
|
|
|
309aa9 |
+
|
|
|
309aa9 |
+ _bind_manager(topology)
|
|
|
309aa9 |
+ _write_aci_production(topology, mod_type=ldap.MOD_DELETE)
|
|
|
309aa9 |
+ _bind_normal(topology)
|
|
|
309aa9 |
+
|
|
|
309aa9 |
# successfull MOD with the both ACI
|
|
|
309aa9 |
_bind_manager(topology)
|
|
|
309aa9 |
_moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_DELETE, target_from=STAGING_DN, target_to=PRODUCTION_DN)
|
|
|
309aa9 |
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
|
|
|
309aa9 |
index 6a4982c..4129318 100644
|
|
|
309aa9 |
--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
|
|
|
309aa9 |
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
|
|
|
309aa9 |
@@ -677,31 +677,17 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
|
|
|
309aa9 |
|
|
|
309aa9 |
/* JCMACL - Should be performed before the child check. */
|
|
|
309aa9 |
/* JCMACL - Why is the check performed against the copy, rather than the existing entry? */
|
|
|
309aa9 |
+ /* This check must be performed even if the entry is renamed with its own name
|
|
|
309aa9 |
+ * No optimization here we need to check we have the write access to the target entry
|
|
|
309aa9 |
+ */
|
|
|
309aa9 |
+ ldap_result_code = plugin_call_acl_plugin(pb, ec->ep_entry,
|
|
|
309aa9 |
+ NULL /*attr*/, NULL /*value*/, SLAPI_ACL_WRITE,
|
|
|
309aa9 |
+ ACLPLUGIN_ACCESS_MODRDN, &errbuf);
|
|
|
309aa9 |
+ if (ldap_result_code != LDAP_SUCCESS)
|
|
|
309aa9 |
{
|
|
|
309aa9 |
- Slapi_RDN *new_rdn;
|
|
|
309aa9 |
- Slapi_RDN *old_rdn;
|
|
|
309aa9 |
-
|
|
|
309aa9 |
- /* Taken from the entry */
|
|
|
309aa9 |
- old_rdn = slapi_entry_get_srdn(ec->ep_entry);
|
|
|
309aa9 |
-
|
|
|
309aa9 |
- /* Taken from the request */
|
|
|
309aa9 |
- new_rdn = slapi_rdn_new();
|
|
|
309aa9 |
- slapi_sdn_get_rdn(&dn_newrdn, new_rdn);
|
|
|
309aa9 |
-
|
|
|
309aa9 |
- /* Only if we change the RDN value, we need the write access to the entry */
|
|
|
309aa9 |
- if (slapi_rdn_compare(old_rdn, new_rdn)) {
|
|
|
309aa9 |
- ldap_result_code = plugin_call_acl_plugin(pb, ec->ep_entry,
|
|
|
309aa9 |
- NULL /*attr*/, NULL /*value*/, SLAPI_ACL_WRITE,
|
|
|
309aa9 |
- ACLPLUGIN_ACCESS_MODRDN, &errbuf);
|
|
|
309aa9 |
- }
|
|
|
309aa9 |
-
|
|
|
309aa9 |
- slapi_rdn_free(&new_rdn);
|
|
|
309aa9 |
+ goto error_return;
|
|
|
309aa9 |
+ }
|
|
|
309aa9 |
|
|
|
309aa9 |
- if (ldap_result_code != LDAP_SUCCESS) {
|
|
|
309aa9 |
- goto error_return;
|
|
|
309aa9 |
- }
|
|
|
309aa9 |
- }
|
|
|
309aa9 |
-
|
|
|
309aa9 |
/* Set the new dn to the copy of the entry */
|
|
|
309aa9 |
slapi_entry_set_sdn( ec->ep_entry, &dn_newdn );
|
|
|
309aa9 |
if (entryrdn_get_switch()) { /* subtree-rename: on */
|
|
|
309aa9 |
--
|
|
|
309aa9 |
1.9.3
|
|
|
309aa9 |
|