diff options
author | Nadezhda Ivanova <nivanova@symas.com> | 2014-11-04 20:08:58 +0200 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2015-02-03 05:02:11 +0100 |
commit | ac8b8e5539b79407292a5ef19bdd2aaf86b92884 (patch) | |
tree | 0c67cc6518fbbe7aa1bfb7c33d3581cab24e6a1c /source4/dsdb | |
parent | def9d268681625c2431e53d842f22a01af72c95c (diff) | |
download | samba-ac8b8e5539b79407292a5ef19bdd2aaf86b92884.tar.gz samba-ac8b8e5539b79407292a5ef19bdd2aaf86b92884.tar.xz samba-ac8b8e5539b79407292a5ef19bdd2aaf86b92884.zip |
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
Diffstat (limited to 'source4/dsdb')
-rwxr-xr-x | source4/dsdb/tests/python/acl.py | 132 |
1 files changed, 131 insertions, 1 deletions
diff --git a/source4/dsdb/tests/python/acl.py b/source4/dsdb/tests/python/acl.py index 4acc12349f..d8e8962993 100755 --- a/source4/dsdb/tests/python/acl.py +++ b/source4/dsdb/tests/python/acl.py @@ -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): |