1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

s4-dsdb: Tests for security checks on undelete operation

Implemented according to MS-ADTS 3.1.1.5.3.7.1. Unfortunately it appears
LC is also necessary, and it is not granted by default to anyone but
System and Administrator, so tests had to be done negatively

Signed-off-by: Nadezhda Ivanova <nivanova@symas.com>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Change-Id: Ic03b8fc4e222e7842ec8a9645a1bb33e7df9c438
This commit is contained in:
Nadezhda Ivanova 2014-11-04 20:08:58 +02:00 committed by Andrew Bartlett
parent def9d26868
commit ac8b8e5539
2 changed files with 135 additions and 5 deletions

View File

@ -62,7 +62,7 @@ class SDUtils(object):
def dacl_add_ace(self, object_dn, ace):
"""Add an ACE to an objects security descriptor
"""
desc = self.read_sd_on_dn(object_dn)
desc = self.read_sd_on_dn(object_dn,["show_deleted:1"])
desc_sddl = desc.as_sddl(self.domain_sid)
if ace in desc_sddl:
return
@ -71,10 +71,10 @@ class SDUtils(object):
desc_sddl[desc_sddl.index("("):])
else:
desc_sddl = desc_sddl + ace
self.modify_sd_on_dn(object_dn, desc_sddl)
self.modify_sd_on_dn(object_dn, desc_sddl, ["show_deleted:1"])
def get_sd_as_sddl(self, object_dn, controls=None):
def get_sd_as_sddl(self, object_dn, controls=[]):
"""Return object nTSecutiryDescriptor in SDDL format
"""
desc = self.read_sd_on_dn(object_dn, controls=controls)
desc = self.read_sd_on_dn(object_dn, controls + ["show_deleted:1"])
return desc.as_sddl(self.domain_sid)

View File

@ -20,7 +20,7 @@ from ldb import (
from ldb import ERR_CONSTRAINT_VIOLATION
from ldb import ERR_OPERATIONS_ERROR
from ldb import Message, MessageElement, Dn
from ldb import FLAG_MOD_REPLACE, FLAG_MOD_ADD
from ldb import FLAG_MOD_REPLACE, FLAG_MOD_ADD, FLAG_MOD_DELETE
from samba.dcerpc import security, drsuapi, misc
from samba.auth import system_session
@ -1637,6 +1637,136 @@ class AclExtendedTests(AclTests):
self.assertEqual(len(res),1)
self.assertTrue("nTSecurityDescriptor" in res[0].keys())
class AclUndeleteTests(AclTests):
def setUp(self):
super(AclUndeleteTests, self).setUp()
self.regular_user = "undeleter1"
self.ou1 = "OU=undeleted_ou,"
self.testuser1 = "to_be_undeleted1"
self.testuser2 = "to_be_undeleted2"
self.testuser3 = "to_be_undeleted3"
self.testuser4 = "to_be_undeleted4"
self.testuser5 = "to_be_undeleted5"
self.testuser6 = "to_be_undeleted6"
self.new_dn_ou = "CN="+ self.testuser4 + "," + self.ou1 + self.base_dn
# Create regular user
self.testuser1_dn = self.get_user_dn(self.testuser1)
self.testuser2_dn = self.get_user_dn(self.testuser2)
self.testuser3_dn = self.get_user_dn(self.testuser3)
self.testuser4_dn = self.get_user_dn(self.testuser4)
self.testuser5_dn = self.get_user_dn(self.testuser5)
self.deleted_dn1 = self.create_delete_user(self.testuser1)
self.deleted_dn2 = self.create_delete_user(self.testuser2)
self.deleted_dn3 = self.create_delete_user(self.testuser3)
self.deleted_dn4 = self.create_delete_user(self.testuser4)
self.deleted_dn5 = self.create_delete_user(self.testuser5)
self.ldb_admin.create_ou(self.ou1 + self.base_dn)
self.ldb_admin.newuser(self.regular_user, self.user_pass)
self.ldb_admin.add_remove_group_members("Domain Admins", [self.regular_user],
add_members_operation=True)
self.ldb_user = self.get_ldb_connection(self.regular_user, self.user_pass)
self.sid = self.sd_utils.get_object_sid(self.get_user_dn(self.regular_user))
def tearDown(self):
super(AclUndeleteTests, self).tearDown()
delete_force(self.ldb_admin, self.get_user_dn(self.regular_user))
delete_force(self.ldb_admin, self.get_user_dn(self.testuser1))
delete_force(self.ldb_admin, self.get_user_dn(self.testuser2))
delete_force(self.ldb_admin, self.get_user_dn(self.testuser3))
delete_force(self.ldb_admin, self.get_user_dn(self.testuser4))
delete_force(self.ldb_admin, self.get_user_dn(self.testuser5))
delete_force(self.ldb_admin, self.new_dn_ou)
delete_force(self.ldb_admin, self.ou1 + self.base_dn)
def GUID_string(self, guid):
return ldb.schema_format_value("objectGUID", guid)
def create_delete_user(self, new_user):
self.ldb_admin.newuser(new_user, self.user_pass)
res = self.ldb_admin.search(expression="(objectClass=*)",
base=self.get_user_dn(new_user),
scope=SCOPE_BASE,
controls=["show_deleted:1"])
guid = res[0]["objectGUID"][0]
self.ldb_admin.delete(self.get_user_dn(new_user))
res = self.ldb_admin.search(base="<GUID=%s>" % self.GUID_string(guid),
scope=SCOPE_BASE, controls=["show_deleted:1"])
self.assertEquals(len(res), 1)
return str(res[0].dn)
def undelete_deleted(self, olddn, newdn):
msg = Message()
msg.dn = Dn(self.ldb_user, olddn)
msg["isDeleted"] = MessageElement([], FLAG_MOD_DELETE, "isDeleted")
msg["distinguishedName"] = MessageElement([newdn], FLAG_MOD_REPLACE, "distinguishedName")
res = self.ldb_user.modify(msg, ["show_recycled:1"])
def undelete_deleted_with_mod(self, olddn, newdn):
msg = Message()
msg.dn = Dn(ldb, olddn)
msg["isDeleted"] = MessageElement([], FLAG_MOD_DELETE, "isDeleted")
msg["distinguishedName"] = MessageElement([newdn], FLAG_MOD_REPLACE, "distinguishedName")
msg["url"] = MessageElement(["www.samba.org"], FLAG_MOD_REPLACE, "url")
res = self.ldb_user.modify(msg, ["show_deleted:1"])
def test_undelete(self):
# it appears the user has to have LC on the old parent to be able to move the object
# otherwise we get no such object. Since only System can modify the SD on deleted object
# we cannot grant this permission via LDAP, and this leaves us with "negative" tests at the moment
# deny write property on rdn, should fail
mod = "(OD;;WP;bf967a0e-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.sid)
self.sd_utils.dacl_add_ace(self.deleted_dn1, mod)
try:
self.undelete_deleted(self.deleted_dn1, self.testuser1_dn)
self.fail()
except LdbError, (num, _):
self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
# seems that permissions on isDeleted and distinguishedName are irrelevant
mod = "(OD;;WP;bf96798f-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.sid)
self.sd_utils.dacl_add_ace(self.deleted_dn2, mod)
mod = "(OD;;WP;bf9679e4-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.sid)
self.sd_utils.dacl_add_ace(self.deleted_dn2, mod)
self.undelete_deleted(self.deleted_dn2, self.testuser2_dn)
# attempt undelete with simultanious addition of url, WP to which is denied
mod = "(OD;;WP;9a9a0221-4a5b-11d1-a9c3-0000f80367c1;;%s)" % str(self.sid)
self.sd_utils.dacl_add_ace(self.deleted_dn3, mod)
try:
self.undelete_deleted_with_mod(self.deleted_dn3, self.testuser3_dn)
self.fail()
except LdbError, (num, _):
self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
# undelete in an ou, in which we have no right to create children
mod = "(D;;CC;;;%s)" % str(self.sid)
self.sd_utils.dacl_add_ace(self.ou1 + self.base_dn, mod)
try:
self.undelete_deleted(self.deleted_dn4, self.new_dn_ou)
self.fail()
except LdbError, (num, _):
self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
# delete is not required
mod = "(D;;SD;;;%s)" % str(self.sid)
self.sd_utils.dacl_add_ace(self.deleted_dn5, mod)
self.undelete_deleted(self.deleted_dn5, self.testuser5_dn)
# deny Reanimate-Tombstone, should fail
mod = "(OD;;CR;45ec5156-db7e-47bb-b53f-dbeb2d03c40f;;%s)" % str(self.sid)
self.sd_utils.dacl_add_ace(self.base_dn, mod)
try:
self.undelete_deleted(self.deleted_dn4, self.testuser4_dn)
self.fail()
except LdbError, (num, _):
self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
class AclSPNTests(AclTests):