def run(self, groupname, listofmembers, credopts=None, sambaopts=None, versionopts=None, H=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) try: samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) groupmembers = listofmembers.split(',') samdb.add_remove_group_members(groupname, groupmembers, add_members_operation=True) except Exception, e: # FIXME: catch more specific exception raise CommandError( 'Failed to add members "%s" to group "%s"' % (listofmembers, groupname), e)
def run(self, groupname, listofmembers, credopts=None, sambaopts=None, versionopts=None, H=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) try: samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) samdb.add_remove_group_members(groupname, listofmembers.split(","), add_members_operation=False) except Exception as e: # FIXME: Catch more specific exception raise CommandError( 'Failed to remove members "%s" from group "%s"' % (listofmembers, groupname), e) self.outf.write("Removed members from group %s\n" % groupname)
def run(self, groupname, listofmembers, credopts=None, sambaopts=None, versionopts=None, H=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) try: samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) samdb.add_remove_group_members(groupname, listofmembers, add_members_operation=False) except Exception, e: # FIXME: Catch more specific exception raise CommandError('Failed to remove members "%s" from group "%s"' % (listofmembers, groupname), e)
def run(self, groupname, listofmembers, credopts=None, sambaopts=None, versionopts=None, H=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) try: samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) groupmembers = listofmembers.split(',') samdb.add_remove_group_members(groupname, groupmembers, add_members_operation=True) except Exception, e: # FIXME: catch more specific exception raise CommandError('Failed to add members "{0!s}" to group "{1!s}"'.format( listofmembers, groupname), e)
def run(self, groupname, listofmembers=None, credopts=None, sambaopts=None, versionopts=None, H=None, member_base_dn=None, member_dn=None, object_types="user,group,computer"): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) if member_dn is None and listofmembers is None: self.usage() raise CommandError( 'Either listofmembers or --member-dn must be specified.') try: samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) groupmembers = [] if member_dn is not None: groupmembers += member_dn if listofmembers is not None: groupmembers += listofmembers.split(',') group_member_types = object_types.split(',') if member_base_dn is not None: member_base_dn = samdb.normalize_dn_in_domain(member_base_dn) samdb.add_remove_group_members(groupname, groupmembers, add_members_operation=False, member_types=group_member_types, member_base_dn=member_base_dn) except Exception as e: # FIXME: Catch more specific exception raise CommandError( 'Failed to remove members %r from group "%s"' % (listofmembers, groupname), e) self.outf.write("Removed members from group %s\n" % groupname)
def run(self, groupname, listofmembers, credopts=None, sambaopts=None, versionopts=None, H=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) try: samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) samdb.add_remove_group_members(groupname, listofmembers, add_members_operation=False) except Exception, e: raise CommandError( 'Failed to remove members "%s" from group "%s"' % (listofmembers, groupname), e)
class GroupAuditTests(AuditLogTestBase): def setUp(self): self.message_type = MSG_GROUP_LOG self.event_type = DSDB_GROUP_EVENT_NAME super(GroupAuditTests, self).setUp() self.server_ip = os.environ["SERVER_IP"] host = "ldap://%s" % os.environ["SERVER"] self.ldb = SamDB(url=host, session_info=system_session(), credentials=self.get_credentials(), lp=self.get_loadparm()) self.server = os.environ["SERVER"] # Gets back the basedn self.base_dn = self.ldb.domain_dn() # Get the old "dSHeuristics" if it was set dsheuristics = self.ldb.get_dsheuristics() # Set the "dSHeuristics" to activate the correct "userPassword" # behaviour self.ldb.set_dsheuristics("000000001") # Reset the "dSHeuristics" as they were before self.addCleanup(self.ldb.set_dsheuristics, dsheuristics) # Get the old "minPwdAge" minPwdAge = self.ldb.get_minPwdAge() # Set it temporarily to "0" self.ldb.set_minPwdAge("0") self.base_dn = self.ldb.domain_dn() # Reset the "minPwdAge" as it was before self.addCleanup(self.ldb.set_minPwdAge, minPwdAge) # (Re)adds the test user USER_NAME with password USER_PASS self.ldb.add({ "dn": "cn=" + USER_NAME + ",cn=users," + self.base_dn, "objectclass": "user", "sAMAccountName": USER_NAME, "userPassword": USER_PASS }) self.ldb.newgroup(GROUP_NAME_01) self.ldb.newgroup(GROUP_NAME_02) def tearDown(self): super(GroupAuditTests, self).tearDown() delete_force(self.ldb, "cn=" + USER_NAME + ",cn=users," + self.base_dn) self.ldb.deletegroup(GROUP_NAME_01) self.ldb.deletegroup(GROUP_NAME_02) def test_add_and_remove_users_from_group(self): # # Wait for the primary group change for the created user. # messages = self.waitForMessages(2) print("Received %d messages" % len(messages)) self.assertEquals(2, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] self.assertEqual("PrimaryGroup", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=domain users,cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") # Check the Add message for the new users primary group audit = messages[1]["groupChange"] self.assertEqual("Added", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=domain users,cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) self.assertEquals(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP, audit["eventId"]) # # Add the user to a group # self.discardMessages() self.ldb.add_remove_group_members(GROUP_NAME_01, [USER_NAME]) messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) self.assertEquals(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] self.assertEqual("Added", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_01 + ",cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") # # Add the user to another group # self.discardMessages() self.ldb.add_remove_group_members(GROUP_NAME_02, [USER_NAME]) messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) self.assertEquals(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] self.assertEqual("Added", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_02 + ",cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") # # Remove the user from a group # self.discardMessages() self.ldb.add_remove_group_members(GROUP_NAME_01, [USER_NAME], add_members_operation=False) messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) self.assertEquals(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] self.assertEqual("Removed", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_01 + ",cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") # # Re-add the user to a group # self.discardMessages() self.ldb.add_remove_group_members(GROUP_NAME_01, [USER_NAME]) messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) self.assertEquals(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] self.assertEqual("Added", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_01 + ",cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") def test_change_primary_group(self): # # Wait for the primary group change for the created user. # messages = self.waitForMessages(2) print("Received %d messages" % len(messages)) self.assertEquals(2, len(messages), "Did not receive the expected number of messages") # Check the PrimaryGroup message audit = messages[0]["groupChange"] self.assertEqual("PrimaryGroup", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=domain users,cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") # Check the Add message for the new users primary group audit = messages[1]["groupChange"] self.assertEqual("Added", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=domain users,cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) self.assertEquals(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP, audit["eventId"]) # # Add the user to a group, the user needs to be a member of a group # before there primary group can be set to that group. # self.discardMessages() self.ldb.add_remove_group_members(GROUP_NAME_01, [USER_NAME]) messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) self.assertEquals(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] self.assertEqual("Added", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_01 + ",cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") self.assertEquals(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP, audit["eventId"]) # # Change the primary group of a user # user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_01 + ",cn=users," + self.base_dn # get the primaryGroupToken of the group res = self.ldb.search(base=group_dn, attrs=["primaryGroupToken"], scope=ldb.SCOPE_BASE) group_id = res[0]["primaryGroupToken"] # set primaryGroupID attribute of the user to that group m = ldb.Message() m.dn = ldb.Dn(self.ldb, user_dn) m["primaryGroupID"] = ldb.MessageElement(group_id, FLAG_MOD_REPLACE, "primaryGroupID") self.discardMessages() self.ldb.modify(m) # # Wait for the primary group change. # Will see the user removed from the new group # the user added to their old primary group # and a new primary group event. # messages = self.waitForMessages(3) print("Received %d messages" % len(messages)) self.assertEquals(3, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] self.assertEqual("Removed", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_01 + ",cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") self.assertEquals(EVT_ID_USER_REMOVED_FROM_GLOBAL_SEC_GROUP, audit["eventId"]) audit = messages[1]["groupChange"] self.assertEqual("Added", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=domain users,cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") self.assertEquals(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP, audit["eventId"]) audit = messages[2]["groupChange"] self.assertEqual("PrimaryGroup", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_01 + ",cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP")
class RodcCmdTestCase(SambaToolCmdTest): def setUp(self): super(RodcCmdTestCase, self).setUp() self.lp = samba.param.LoadParm() self.lp.load(os.environ["SMB_CONF_PATH"]) self.creds = Credentials() self.creds.set_username(os.environ["DC_USERNAME"]) self.creds.set_password(os.environ["DC_PASSWORD"]) self.creds.guess(self.lp) self.session = system_session() self.ldb = SamDB("ldap://" + os.environ["DC_SERVER"], session_info=self.session, credentials=self.creds,lp=self.lp) self.base_dn = self.ldb.domain_dn() self.ldb.newuser("sambatool1", "1qazXSW@") self.ldb.newuser("sambatool2", "2wsxCDE#") self.ldb.newuser("sambatool3", "3edcVFR$") self.ldb.newuser("sambatool4", "4rfvBGT%") self.ldb.newuser("sambatool5", "5tjbNHY*") self.ldb.newuser("sambatool6", "6yknMJU*") self.ldb.add_remove_group_members("Allowed RODC Password Replication Group", ["sambatool1", "sambatool2", "sambatool3", "sambatool4", "sambatool5"], add_members_operation=True) def tearDown(self): super(RodcCmdTestCase, self).tearDown() self.ldb.deleteuser("sambatool1") self.ldb.deleteuser("sambatool2") self.ldb.deleteuser("sambatool3") self.ldb.deleteuser("sambatool4") self.ldb.deleteuser("sambatool5") self.ldb.deleteuser("sambatool6") (result, out, err) = self.runsubcmd("drs", "replicate", "--local", "unused", os.environ["DC_SERVER"], self.base_dn) def test_single_by_account_name(self): (result, out, err) = self.runsubcmd("rodc", "preload", "sambatool1", "--server", os.environ["DC_SERVER"]) self.assertCmdSuccess(result, out, err, "ensuring rodc prefetch ran successfully") self.assertEqual(out, "Replicating DN CN=sambatool1,CN=Users,%s\n" % self.base_dn) self.assertEqual(err, "") def test_single_by_dn(self): (result, out, err) = self.runsubcmd("rodc", "preload", "cn=sambatool2,cn=users,%s" % self.base_dn, "--server", os.environ["DC_SERVER"]) self.assertCmdSuccess(result, out, err, "ensuring rodc prefetch ran successfully") self.assertEqual(out, "Replicating DN CN=sambatool2,CN=Users,%s\n" % self.base_dn) def test_multi_by_account_name(self): (result, out, err) = self.runsubcmd("rodc", "preload", "sambatool1", "sambatool2", "--server", os.environ["DC_SERVER"]) self.assertCmdSuccess(result, out, err, "ensuring rodc prefetch ran successfully") self.assertEqual(out, "Replicating DN CN=sambatool1,CN=Users,%s\nReplicating DN CN=sambatool2,CN=Users,%s\n" % (self.base_dn, self.base_dn)) def test_multi_by_dn(self): (result, out, err) = self.runsubcmd("rodc", "preload", "cn=sambatool3,cn=users,%s" % self.base_dn, "cn=sambatool4,cn=users,%s" % self.base_dn, "--server", os.environ["DC_SERVER"]) self.assertCmdSuccess(result, out, err, "ensuring rodc prefetch ran successfully") self.assertEqual(out, "Replicating DN CN=sambatool3,CN=Users,%s\nReplicating DN CN=sambatool4,CN=Users,%s\n" % (self.base_dn, self.base_dn)) def test_multi_in_file(self): tempf = os.path.join(self.tempdir, "accountlist") open(tempf, 'w').write("sambatool1\nsambatool2") (result, out, err) = self.runsubcmd("rodc", "preload", "--file", tempf, "--server", os.environ["DC_SERVER"]) self.assertCmdSuccess(result, out, err, "ensuring rodc prefetch ran successfully") self.assertEqual(out, "Replicating DN CN=sambatool1,CN=Users,%s\nReplicating DN CN=sambatool2,CN=Users,%s\n" % (self.base_dn, self.base_dn)) os.unlink(tempf) def test_multi_with_missing_name_success(self): (result, out, err) = self.runsubcmd("rodc", "preload", "nonexistentuser1", "sambatool5", "nonexistentuser2", "--server", os.environ["DC_SERVER"], "--ignore-errors") self.assertCmdSuccess(result, out, err, "ensuring rodc prefetch ran successfully") self.assertTrue(out.startswith("Replicating DN CN=sambatool5,CN=Users,%s\n" % self.base_dn)) def test_multi_with_missing_name_failure(self): (result, out, err) = self.runsubcmd("rodc", "preload", "nonexistentuser1", "sambatool5", "nonexistentuser2", "--server", os.environ["DC_SERVER"]) self.assertCmdFail(result, "ensuring rodc prefetch quit on missing user") def test_multi_without_group_success(self): (result, out, err) = self.runsubcmd("rodc", "preload", "sambatool6", "sambatool5", "--server", os.environ["DC_SERVER"], "--ignore-errors") self.assertCmdSuccess(result, out, err, "ensuring rodc prefetch ran successfully") self.assertTrue(out.startswith("Replicating DN CN=sambatool6,CN=Users,%s\n" "Replicating DN CN=sambatool5,CN=Users,%s\n" % (self.base_dn, self.base_dn))) def test_multi_without_group_failure(self): (result, out, err) = self.runsubcmd("rodc", "preload", "sambatool6", "sambatool5", "--server", os.environ["DC_SERVER"]) self.assertCmdFail(result, "ensuring rodc prefetch quit on non-replicated user")
class DynamicTokenTest(samba.tests.TestCase): def get_creds(self, target_username, target_password): creds_tmp = Credentials() creds_tmp.set_username(target_username) creds_tmp.set_password(target_password) creds_tmp.set_domain(creds.get_domain()) creds_tmp.set_realm(creds.get_realm()) creds_tmp.set_workstation(creds.get_workstation()) creds_tmp.set_gensec_features(creds_tmp.get_gensec_features() | gensec.FEATURE_SEAL) return creds_tmp def get_ldb_connection(self, target_username, target_password): creds_tmp = self.get_creds(target_username, target_password) ldb_target = SamDB(url=url, credentials=creds_tmp, lp=lp) return ldb_target def setUp(self): super(DynamicTokenTest, self).setUp() self.admin_ldb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp) self.base_dn = self.admin_ldb.domain_dn() self.test_user = "******" self.test_user_pass = "******" self.admin_ldb.newuser(self.test_user, self.test_user_pass) self.test_group0 = "tokengroups_group0" self.admin_ldb.newgroup(self.test_group0, grouptype=dsdb.GTYPE_SECURITY_DOMAIN_LOCAL_GROUP) res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group0, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE) self.test_group0_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group0, [self.test_user], add_members_operation=True) self.test_group1 = "tokengroups_group1" self.admin_ldb.newgroup(self.test_group1, grouptype=dsdb.GTYPE_SECURITY_GLOBAL_GROUP) res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group1, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE) self.test_group1_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group1, [self.test_user], add_members_operation=True) self.test_group2 = "tokengroups_group2" self.admin_ldb.newgroup(self.test_group2, grouptype=dsdb.GTYPE_SECURITY_UNIVERSAL_GROUP) res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group2, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE) self.test_group2_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group2, [self.test_user], add_members_operation=True) self.test_group3 = "tokengroups_group3" self.admin_ldb.newgroup(self.test_group3, grouptype=dsdb.GTYPE_SECURITY_UNIVERSAL_GROUP) res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group3, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE) self.test_group3_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group3, [self.test_group1], add_members_operation=True) self.test_group4 = "tokengroups_group4" self.admin_ldb.newgroup(self.test_group4, grouptype=dsdb.GTYPE_SECURITY_UNIVERSAL_GROUP) res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group4, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE) self.test_group4_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group4, [self.test_group3], add_members_operation=True) self.test_group5 = "tokengroups_group5" self.admin_ldb.newgroup(self.test_group5, grouptype=dsdb.GTYPE_SECURITY_DOMAIN_LOCAL_GROUP) res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group5, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE) self.test_group5_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group5, [self.test_group4], add_members_operation=True) self.test_group6 = "tokengroups_group6" self.admin_ldb.newgroup(self.test_group6, grouptype=dsdb.GTYPE_SECURITY_DOMAIN_LOCAL_GROUP) res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group6, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE) self.test_group6_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group6, [self.test_user], add_members_operation=True) self.ldb = self.get_ldb_connection(self.test_user, self.test_user_pass) res = self.ldb.search("", scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) self.assertEquals(len(res), 1) self.user_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["tokenGroups"][0]) self.user_sid_dn = "<SID=%s>" % str(self.user_sid) res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=[]) self.assertEquals(len(res), 1) self.test_user_dn = res[0].dn session_info_flags = ( AUTH_SESSION_INFO_DEFAULT_GROUPS | AUTH_SESSION_INFO_AUTHENTICATED | AUTH_SESSION_INFO_SIMPLE_PRIVILEGES) session = samba.auth.user_session(self.ldb, lp_ctx=lp, dn=self.user_sid_dn, session_info_flags=session_info_flags) token = session.security_token self.user_sids = [] for s in token.sids: self.user_sids.append(str(s)) def tearDown(self): super(DynamicTokenTest, self).tearDown() delete_force(self.admin_ldb, "CN=%s,%s,%s" % (self.test_user, "cn=users", self.base_dn)) delete_force(self.admin_ldb, "CN=%s,%s,%s" % (self.test_group0, "cn=users", self.base_dn)) delete_force(self.admin_ldb, "CN=%s,%s,%s" % (self.test_group1, "cn=users", self.base_dn)) delete_force(self.admin_ldb, "CN=%s,%s,%s" % (self.test_group2, "cn=users", self.base_dn)) delete_force(self.admin_ldb, "CN=%s,%s,%s" % (self.test_group3, "cn=users", self.base_dn)) delete_force(self.admin_ldb, "CN=%s,%s,%s" % (self.test_group4, "cn=users", self.base_dn)) delete_force(self.admin_ldb, "CN=%s,%s,%s" % (self.test_group5, "cn=users", self.base_dn)) delete_force(self.admin_ldb, "CN=%s,%s,%s" % (self.test_group6, "cn=users", self.base_dn)) def test_rootDSE_tokenGroups(self): """Testing rootDSE tokengroups against internal calculation""" if not url.startswith("ldap"): self.fail(msg="This test is only valid on ldap") res = self.ldb.search("", scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) self.assertEquals(len(res), 1) print("Getting tokenGroups from rootDSE") tokengroups = [] for sid in res[0]['tokenGroups']: tokengroups.append(str(ndr_unpack(samba.dcerpc.security.dom_sid, sid))) sidset1 = set(tokengroups) sidset2 = set(self.user_sids) if len(sidset1.difference(sidset2)): print("token sids don't match") print("tokengroups: %s" % tokengroups) print("calculated : %s" % self.user_sids) print("difference : %s" % sidset1.difference(sidset2)) self.fail(msg="calculated groups don't match against rootDSE tokenGroups") def test_dn_tokenGroups(self): print("Getting tokenGroups from user DN") res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) self.assertEquals(len(res), 1) dn_tokengroups = [] for sid in res[0]['tokenGroups']: dn_tokengroups.append(str(ndr_unpack(samba.dcerpc.security.dom_sid, sid))) sidset1 = set(dn_tokengroups) sidset2 = set(self.user_sids) if len(sidset1.difference(sidset2)): print("token sids don't match") print("difference : %s" % sidset1.difference(sidset2)) self.fail(msg="calculated groups don't match against user DN tokenGroups") def test_pac_groups(self): settings = {} settings["lp_ctx"] = lp settings["target_hostname"] = lp.get("netbios name") gensec_client = gensec.Security.start_client(settings) gensec_client.set_credentials(self.get_creds(self.test_user, self.test_user_pass)) gensec_client.want_feature(gensec.FEATURE_SEAL) gensec_client.start_mech_by_sasl_name("GSSAPI") auth_context = AuthContext(lp_ctx=lp, ldb=self.ldb, methods=[]) gensec_server = gensec.Security.start_server(settings, auth_context) machine_creds = Credentials() machine_creds.guess(lp) machine_creds.set_machine_account(lp) gensec_server.set_credentials(machine_creds) gensec_server.want_feature(gensec.FEATURE_SEAL) gensec_server.start_mech_by_sasl_name("GSSAPI") client_finished = False server_finished = False server_to_client = "" # Run the actual call loop. while client_finished == False and server_finished == False: if not client_finished: print "running client gensec_update" (client_finished, client_to_server) = gensec_client.update(server_to_client) if not server_finished: print "running server gensec_update" (server_finished, server_to_client) = gensec_server.update(client_to_server) session = gensec_server.session_info() token = session.security_token pac_sids = [] for s in token.sids: pac_sids.append(str(s)) sidset1 = set(pac_sids) sidset2 = set(self.user_sids) if len(sidset1.difference(sidset2)): print("token sids don't match") print("difference : %s" % sidset1.difference(sidset2)) self.fail(msg="calculated groups don't match against user PAC tokenGroups") def test_tokenGroups_manual(self): # Manually run the tokenGroups algorithm from MS-ADTS 3.1.1.4.5.19 and MS-DRSR 4.1.8.3 # and compare the result res = self.admin_ldb.search(base=self.base_dn, scope=ldb.SCOPE_SUBTREE, expression="(|(objectclass=user)(objectclass=group))", attrs=["memberOf"]) aSet = set() aSetR = set() vSet = set() for obj in res: if "memberOf" in obj: for dn in obj["memberOf"]: first = obj.dn.get_casefold() second = ldb.Dn(self.admin_ldb, dn).get_casefold() aSet.add((first, second)) aSetR.add((second, first)) vSet.add(first) vSet.add(second) res = self.admin_ldb.search(base=self.base_dn, scope=ldb.SCOPE_SUBTREE, expression="(objectclass=user)", attrs=["primaryGroupID"]) for obj in res: if "primaryGroupID" in obj: sid = "%s-%d" % (self.admin_ldb.get_domain_sid(), int(obj["primaryGroupID"][0])) res2 = self.admin_ldb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE, attrs=[]) first = obj.dn.get_casefold() second = res2[0].dn.get_casefold() aSet.add((first, second)) aSetR.add((second, first)) vSet.add(first) vSet.add(second) wSet = set() wSet.add(self.test_user_dn.get_casefold()) closure(vSet, wSet, aSet) wSet.remove(self.test_user_dn.get_casefold()) tokenGroupsSet = set() res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) self.assertEquals(len(res), 1) dn_tokengroups = [] for sid in res[0]['tokenGroups']: sid = ndr_unpack(samba.dcerpc.security.dom_sid, sid) res3 = self.admin_ldb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE, attrs=[]) tokenGroupsSet.add(res3[0].dn.get_casefold()) if len(wSet.difference(tokenGroupsSet)): self.fail(msg="additional calculated: %s" % wSet.difference(tokenGroupsSet)) if len(tokenGroupsSet.difference(wSet)): self.fail(msg="additional tokenGroups: %s" % tokenGroupsSet.difference(wSet)) def filtered_closure(self, wSet, filter_grouptype): res = self.admin_ldb.search(base=self.base_dn, scope=ldb.SCOPE_SUBTREE, expression="(|(objectclass=user)(objectclass=group))", attrs=["memberOf"]) aSet = set() aSetR = set() vSet = set() for obj in res: vSet.add(obj.dn.get_casefold()) if "memberOf" in obj: for dn in obj["memberOf"]: first = obj.dn.get_casefold() second = ldb.Dn(self.admin_ldb, dn).get_casefold() aSet.add((first, second)) aSetR.add((second, first)) vSet.add(first) vSet.add(second) res = self.admin_ldb.search(base=self.base_dn, scope=ldb.SCOPE_SUBTREE, expression="(objectclass=user)", attrs=["primaryGroupID"]) for obj in res: if "primaryGroupID" in obj: sid = "%s-%d" % (self.admin_ldb.get_domain_sid(), int(obj["primaryGroupID"][0])) res2 = self.admin_ldb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE, attrs=[]) first = obj.dn.get_casefold() second = res2[0].dn.get_casefold() aSet.add((first, second)) aSetR.add((second, first)) vSet.add(first) vSet.add(second) uSet = set() for v in vSet: res_group = self.admin_ldb.search(base=v, scope=ldb.SCOPE_BASE, attrs=["groupType"], expression="objectClass=group") if len(res_group) == 1: if hex(int(res_group[0]["groupType"][0]) & 0x00000000FFFFFFFF) == hex(filter_grouptype): uSet.add(v) else: uSet.add(v) closure(uSet, wSet, aSet) def test_tokenGroupsGlobalAndUniversal_manual(self): # Manually run the tokenGroups algorithm from MS-ADTS 3.1.1.4.5.19 and MS-DRSR 4.1.8.3 # and compare the result # The variable names come from MS-ADTS May 15, 2014 S = set() S.add(self.test_user_dn.get_casefold()) self.filtered_closure(S, GTYPE_SECURITY_GLOBAL_GROUP) T = set() # Not really a SID, we do this on DNs... for sid in S: X = set() X.add(sid) self.filtered_closure(X, GTYPE_SECURITY_UNIVERSAL_GROUP) T = T.union(X) T.remove(self.test_user_dn.get_casefold()) tokenGroupsSet = set() res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["tokenGroupsGlobalAndUniversal"]) self.assertEquals(len(res), 1) dn_tokengroups = [] for sid in res[0]['tokenGroupsGlobalAndUniversal']: sid = ndr_unpack(samba.dcerpc.security.dom_sid, sid) res3 = self.admin_ldb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE, attrs=[]) tokenGroupsSet.add(res3[0].dn.get_casefold()) if len(T.difference(tokenGroupsSet)): self.fail(msg="additional calculated: %s" % T.difference(tokenGroupsSet)) if len(tokenGroupsSet.difference(T)): self.fail(msg="additional tokenGroupsGlobalAndUniversal: %s" % tokenGroupsSet.difference(T)) def test_samr_GetGroupsForUser(self): # Confirm that we get the correct results against SAMR also if not url.startswith("ldap://"): self.fail(msg="This test is only valid on ldap (so we an find the hostname and use SAMR)") host = url.split("://")[1] (domain_sid, user_rid) = self.user_sid.split() samr_conn = samba.dcerpc.samr.samr("ncacn_ip_tcp:%s[seal]" % host, lp, creds) samr_handle = samr_conn.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED) samr_domain = samr_conn.OpenDomain(samr_handle, security.SEC_FLAG_MAXIMUM_ALLOWED, domain_sid) user_handle = samr_conn.OpenUser(samr_domain, security.SEC_FLAG_MAXIMUM_ALLOWED, user_rid) rids = samr_conn.GetGroupsForUser(user_handle) samr_dns = set() for rid in rids.rids: self.assertEqual(rid.attributes, samr.SE_GROUP_MANDATORY | samr.SE_GROUP_ENABLED_BY_DEFAULT| samr.SE_GROUP_ENABLED) sid = "%s-%d" % (domain_sid, rid.rid) res = self.admin_ldb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE, attrs=[]) samr_dns.add(res[0].dn.get_casefold()) user_info = samr_conn.QueryUserInfo(user_handle, 1) self.assertEqual(rids.rids[0].rid, user_info.primary_gid) tokenGroupsSet = set() res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["tokenGroupsGlobalAndUniversal"]) for sid in res[0]['tokenGroupsGlobalAndUniversal']: sid = ndr_unpack(samba.dcerpc.security.dom_sid, sid) res3 = self.admin_ldb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE, attrs=[], expression="(&(|(grouptype=%d)(grouptype=%d))(objectclass=group))" % (GTYPE_SECURITY_GLOBAL_GROUP, GTYPE_SECURITY_UNIVERSAL_GROUP)) if len(res) == 1: tokenGroupsSet.add(res3[0].dn.get_casefold()) if len(samr_dns.difference(tokenGroupsSet)): self.fail(msg="additional samr_GetUserGroups over tokenGroups: %s" % samr_dns.difference(tokenGroupsSet)) memberOf = set() # Add the primary group primary_group_sid = "%s-%d" % (domain_sid, user_info.primary_gid) res2 = self.admin_ldb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE, attrs=[]) memberOf.add(res2[0].dn.get_casefold()) res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["memberOf"]) for dn in res[0]['memberOf']: res3 = self.admin_ldb.search(base=dn, scope=ldb.SCOPE_BASE, attrs=[], expression="(&(|(grouptype=%d)(grouptype=%d))(objectclass=group))" % (GTYPE_SECURITY_GLOBAL_GROUP, GTYPE_SECURITY_UNIVERSAL_GROUP)) if len(res3) == 1: memberOf.add(res3[0].dn.get_casefold()) if len(memberOf.difference(samr_dns)): self.fail(msg="additional memberOf over samr_GetUserGroups: %s" % memberOf.difference(samr_dns)) if len(samr_dns.difference(memberOf)): self.fail(msg="additional samr_GetUserGroups over memberOf: %s" % samr_dns.difference(memberOf)) S = set() S.add(self.test_user_dn.get_casefold()) self.filtered_closure(S, GTYPE_SECURITY_GLOBAL_GROUP) self.filtered_closure(S, GTYPE_SECURITY_UNIVERSAL_GROUP) # Now remove the user DN and primary group S.remove(self.test_user_dn.get_casefold()) if len(samr_dns.difference(S)): self.fail(msg="additional samr_GetUserGroups over filtered_closure: %s" % samr_dns.difference(S)) def test_samr_GetGroupsForUser_nomember(self): # Confirm that we get the correct results against SAMR also if not url.startswith("ldap://"): self.fail(msg="This test is only valid on ldap (so we an find the hostname and use SAMR)") host = url.split("://")[1] test_user = "******" self.admin_ldb.newuser(test_user, self.test_user_pass) res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (test_user, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE) user_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) (domain_sid, user_rid) = user_sid.split() samr_conn = samba.dcerpc.samr.samr("ncacn_ip_tcp:%s[seal]" % host, lp, creds) samr_handle = samr_conn.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED) samr_domain = samr_conn.OpenDomain(samr_handle, security.SEC_FLAG_MAXIMUM_ALLOWED, domain_sid) user_handle = samr_conn.OpenUser(samr_domain, security.SEC_FLAG_MAXIMUM_ALLOWED, user_rid) rids = samr_conn.GetGroupsForUser(user_handle) user_info = samr_conn.QueryUserInfo(user_handle, 1) delete_force(self.admin_ldb, "CN=%s,%s,%s" % (test_user, "cn=users", self.base_dn)) self.assertEqual(len(rids.rids), 1) self.assertEqual(rids.rids[0].rid, user_info.primary_gid)
class GroupAuditTests(AuditLogTestBase): def setUp(self): self.message_type = MSG_GROUP_LOG self.event_type = DSDB_GROUP_EVENT_NAME super(GroupAuditTests, self).setUp() self.remoteAddress = os.environ["CLIENT_IP"] self.server_ip = os.environ["SERVER_IP"] host = "ldap://%s" % os.environ["SERVER"] self.ldb = SamDB(url=host, session_info=system_session(), credentials=self.get_credentials(), lp=self.get_loadparm()) self.server = os.environ["SERVER"] # Gets back the basedn self.base_dn = self.ldb.domain_dn() # Get the old "dSHeuristics" if it was set dsheuristics = self.ldb.get_dsheuristics() # Set the "dSHeuristics" to activate the correct "userPassword" # behaviour self.ldb.set_dsheuristics("000000001") # Reset the "dSHeuristics" as they were before self.addCleanup(self.ldb.set_dsheuristics, dsheuristics) # Get the old "minPwdAge" minPwdAge = self.ldb.get_minPwdAge() # Set it temporarily to "0" self.ldb.set_minPwdAge("0") self.base_dn = self.ldb.domain_dn() # Reset the "minPwdAge" as it was before self.addCleanup(self.ldb.set_minPwdAge, minPwdAge) # (Re)adds the test user USER_NAME with password USER_PASS self.ldb.add({ "dn": "cn=" + USER_NAME + ",cn=users," + self.base_dn, "objectclass": "user", "sAMAccountName": USER_NAME, "userPassword": USER_PASS }) self.ldb.newgroup(GROUP_NAME_01) self.ldb.newgroup(GROUP_NAME_02) def tearDown(self): super(GroupAuditTests, self).tearDown() delete_force(self.ldb, "cn=" + USER_NAME + ",cn=users," + self.base_dn) self.ldb.deletegroup(GROUP_NAME_01) self.ldb.deletegroup(GROUP_NAME_02) def test_add_and_remove_users_from_group(self): # # Wait for the primary group change for the created user. # messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) self.assertEquals(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] self.assertEqual("PrimaryGroup", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=domain users,cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") # # Add the user to a group # self.discardMessages() self.ldb.add_remove_group_members(GROUP_NAME_01, [USER_NAME]) messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) self.assertEquals(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] self.assertEqual("Added", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_01 + ",cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") # # Add the user to another group # self.discardMessages() self.ldb.add_remove_group_members(GROUP_NAME_02, [USER_NAME]) messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) self.assertEquals(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] self.assertEqual("Added", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_02 + ",cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") # # Remove the user from a group # self.discardMessages() self.ldb.add_remove_group_members( GROUP_NAME_01, [USER_NAME], add_members_operation=False) messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) self.assertEquals(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] self.assertEqual("Removed", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_01 + ",cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") # # Re-add the user to a group # self.discardMessages() self.ldb.add_remove_group_members(GROUP_NAME_01, [USER_NAME]) messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) self.assertEquals(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] self.assertEqual("Added", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_01 + ",cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") def test_change_primary_group(self): # # Wait for the primary group change for the created user. # messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) self.assertEquals(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] self.assertEqual("PrimaryGroup", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=domain users,cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") # # Add the user to a group, the user needs to be a member of a group # before there primary group can be set to that group. # self.discardMessages() self.ldb.add_remove_group_members(GROUP_NAME_01, [USER_NAME]) messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) self.assertEquals(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] self.assertEqual("Added", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_01 + ",cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") # # Change the primary group of a user # user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_01 + ",cn=users," + self.base_dn # get the primaryGroupToken of the group res = self.ldb.search(base=group_dn, attrs=["primaryGroupToken"], scope=ldb.SCOPE_BASE) group_id = res[0]["primaryGroupToken"] # set primaryGroupID attribute of the user to that group m = ldb.Message() m.dn = ldb.Dn(self.ldb, user_dn) m["primaryGroupID"] = ldb.MessageElement( group_id, FLAG_MOD_REPLACE, "primaryGroupID") self.discardMessages() self.ldb.modify(m) # # Wait for the primary group change. # Will see the user removed from the new group # the user added to their old primary group # and a new primary group event. # messages = self.waitForMessages(3) print("Received %d messages" % len(messages)) self.assertEquals(3, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] self.assertEqual("Removed", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_01 + ",cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") audit = messages[1]["groupChange"] self.assertEqual("Added", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=domain users,cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") audit = messages[2]["groupChange"] self.assertEqual("PrimaryGroup", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_01 + ",cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP")
class DynamicTokenTest(samba.tests.TestCase): def get_creds(self, target_username, target_password): creds_tmp = Credentials() creds_tmp.set_username(target_username) creds_tmp.set_password(target_password) creds_tmp.set_domain(creds.get_domain()) creds_tmp.set_realm(creds.get_realm()) creds_tmp.set_workstation(creds.get_workstation()) creds_tmp.set_gensec_features(creds_tmp.get_gensec_features() | gensec.FEATURE_SEAL) return creds_tmp def get_ldb_connection(self, target_username, target_password): creds_tmp = self.get_creds(target_username, target_password) ldb_target = SamDB(url=url, credentials=creds_tmp, lp=lp) return ldb_target def setUp(self): super(DynamicTokenTest, self).setUp() self.admin_ldb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp) self.base_dn = self.admin_ldb.domain_dn() self.test_user = "******" self.test_user_pass = "******" self.admin_ldb.newuser(self.test_user, self.test_user_pass) self.test_group0 = "tokengroups_group0" self.admin_ldb.newgroup( self.test_group0, grouptype=dsdb.GTYPE_SECURITY_DOMAIN_LOCAL_GROUP) res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group0, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE) self.test_group0_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group0, [self.test_user], add_members_operation=True) self.test_group1 = "tokengroups_group1" self.admin_ldb.newgroup(self.test_group1, grouptype=dsdb.GTYPE_SECURITY_GLOBAL_GROUP) res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group1, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE) self.test_group1_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group1, [self.test_user], add_members_operation=True) self.test_group2 = "tokengroups_group2" self.admin_ldb.newgroup(self.test_group2, grouptype=dsdb.GTYPE_SECURITY_UNIVERSAL_GROUP) res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group2, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE) self.test_group2_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group2, [self.test_user], add_members_operation=True) self.ldb = self.get_ldb_connection(self.test_user, self.test_user_pass) res = self.ldb.search("", scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) self.assertEquals(len(res), 1) self.user_sid_dn = "<SID=%s>" % str( ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["tokenGroups"][0])) res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=[]) self.assertEquals(len(res), 1) self.test_user_dn = res[0].dn session_info_flags = (AUTH_SESSION_INFO_DEFAULT_GROUPS | AUTH_SESSION_INFO_AUTHENTICATED | AUTH_SESSION_INFO_SIMPLE_PRIVILEGES) session = samba.auth.user_session( self.ldb, lp_ctx=lp, dn=self.user_sid_dn, session_info_flags=session_info_flags) token = session.security_token self.user_sids = [] for s in token.sids: self.user_sids.append(str(s)) def tearDown(self): super(DynamicTokenTest, self).tearDown() delete_force( self.admin_ldb, "CN=%s,%s,%s" % (self.test_user, "cn=users", self.base_dn)) delete_force( self.admin_ldb, "CN=%s,%s,%s" % (self.test_group0, "cn=users", self.base_dn)) delete_force( self.admin_ldb, "CN=%s,%s,%s" % (self.test_group1, "cn=users", self.base_dn)) delete_force( self.admin_ldb, "CN=%s,%s,%s" % (self.test_group2, "cn=users", self.base_dn)) def test_rootDSE_tokenGroups(self): """Testing rootDSE tokengroups against internal calculation""" if not url.startswith("ldap"): self.fail(msg="This test is only valid on ldap") res = self.ldb.search("", scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) self.assertEquals(len(res), 1) print("Getting tokenGroups from rootDSE") tokengroups = [] for sid in res[0]['tokenGroups']: tokengroups.append( str(ndr_unpack(samba.dcerpc.security.dom_sid, sid))) sidset1 = set(tokengroups) sidset2 = set(self.user_sids) if len(sidset1.difference(sidset2)): print("token sids don't match") print("tokengroups: %s" % tokengroups) print("calculated : %s" % self.user_sids) print("difference : %s" % sidset1.difference(sidset2)) self.fail( msg="calculated groups don't match against rootDSE tokenGroups" ) def test_dn_tokenGroups(self): print("Getting tokenGroups from user DN") res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) self.assertEquals(len(res), 1) dn_tokengroups = [] for sid in res[0]['tokenGroups']: dn_tokengroups.append( str(ndr_unpack(samba.dcerpc.security.dom_sid, sid))) sidset1 = set(dn_tokengroups) sidset2 = set(self.user_sids) if len(sidset1.difference(sidset2)): print("token sids don't match") print("difference : %s" % sidset1.difference(sidset2)) self.fail( msg="calculated groups don't match against user DN tokenGroups" ) def test_pac_groups(self): settings = {} settings["lp_ctx"] = lp settings["target_hostname"] = lp.get("netbios name") gensec_client = gensec.Security.start_client(settings) gensec_client.set_credentials( self.get_creds(self.test_user, self.test_user_pass)) gensec_client.want_feature(gensec.FEATURE_SEAL) gensec_client.start_mech_by_sasl_name("GSSAPI") auth_context = AuthContext(lp_ctx=lp, ldb=self.ldb, methods=[]) gensec_server = gensec.Security.start_server(settings, auth_context) machine_creds = Credentials() machine_creds.guess(lp) machine_creds.set_machine_account(lp) gensec_server.set_credentials(machine_creds) gensec_server.want_feature(gensec.FEATURE_SEAL) gensec_server.start_mech_by_sasl_name("GSSAPI") client_finished = False server_finished = False server_to_client = "" # Run the actual call loop. while client_finished == False and server_finished == False: if not client_finished: print "running client gensec_update" (client_finished, client_to_server) = gensec_client.update(server_to_client) if not server_finished: print "running server gensec_update" (server_finished, server_to_client) = gensec_server.update(client_to_server) session = gensec_server.session_info() token = session.security_token pac_sids = [] for s in token.sids: pac_sids.append(str(s)) sidset1 = set(pac_sids) sidset2 = set(self.user_sids) if len(sidset1.difference(sidset2)): print("token sids don't match") print("difference : %s" % sidset1.difference(sidset2)) self.fail( msg="calculated groups don't match against user PAC tokenGroups" ) def test_tokenGroups_manual(self): # Manually run the tokenGroups algorithm from MS-ADTS 3.1.1.4.5.19 and MS-DRSR 4.1.8.3 # and compare the result res = self.admin_ldb.search( base=self.base_dn, scope=ldb.SCOPE_SUBTREE, expression="(|(objectclass=user)(objectclass=group))", attrs=["memberOf"]) aSet = set() aSetR = set() vSet = set() for obj in res: if "memberOf" in obj: for dn in obj["memberOf"]: first = obj.dn.get_casefold() second = ldb.Dn(self.admin_ldb, dn).get_casefold() aSet.add((first, second)) aSetR.add((second, first)) vSet.add(first) vSet.add(second) res = self.admin_ldb.search(base=self.base_dn, scope=ldb.SCOPE_SUBTREE, expression="(objectclass=user)", attrs=["primaryGroupID"]) for obj in res: if "primaryGroupID" in obj: sid = "%s-%d" % (self.admin_ldb.get_domain_sid(), int(obj["primaryGroupID"][0])) res2 = self.admin_ldb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE, attrs=[]) first = obj.dn.get_casefold() second = res2[0].dn.get_casefold() aSet.add((first, second)) aSetR.add((second, first)) vSet.add(first) vSet.add(second) wSet = set() wSet.add(self.test_user_dn.get_casefold()) closure(vSet, wSet, aSet) wSet.remove(self.test_user_dn.get_casefold()) tokenGroupsSet = set() res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) self.assertEquals(len(res), 1) dn_tokengroups = [] for sid in res[0]['tokenGroups']: sid = ndr_unpack(samba.dcerpc.security.dom_sid, sid) res3 = self.admin_ldb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE, attrs=[]) tokenGroupsSet.add(res3[0].dn.get_casefold()) if len(wSet.difference(tokenGroupsSet)): self.fail(msg="additional calculated: %s" % wSet.difference(tokenGroupsSet)) if len(tokenGroupsSet.difference(wSet)): self.fail(msg="additional tokenGroups: %s" % tokenGroupsSet.difference(wSet)) def filtered_closure(self, wSet, filter_grouptype): res = self.admin_ldb.search( base=self.base_dn, scope=ldb.SCOPE_SUBTREE, expression="(|(objectclass=user)(objectclass=group))", attrs=["memberOf"]) aSet = set() aSetR = set() vSet = set() for obj in res: vSet.add(obj.dn.get_casefold()) if "memberOf" in obj: for dn in obj["memberOf"]: first = obj.dn.get_casefold() second = ldb.Dn(self.admin_ldb, dn).get_casefold() aSet.add((first, second)) aSetR.add((second, first)) vSet.add(first) vSet.add(second) res = self.admin_ldb.search(base=self.base_dn, scope=ldb.SCOPE_SUBTREE, expression="(objectclass=user)", attrs=["primaryGroupID"]) for obj in res: if "primaryGroupID" in obj: sid = "%s-%d" % (self.admin_ldb.get_domain_sid(), int(obj["primaryGroupID"][0])) res2 = self.admin_ldb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE, attrs=[]) first = obj.dn.get_casefold() second = res2[0].dn.get_casefold() aSet.add((first, second)) aSetR.add((second, first)) vSet.add(first) vSet.add(second) uSet = set() for v in vSet: res_group = self.admin_ldb.search(base=v, scope=ldb.SCOPE_BASE, attrs=["groupType"], expression="objectClass=group") if len(res_group) == 1: if hex(int(res_group[0]["groupType"][0]) & 0x00000000FFFFFFFF) == hex(filter_grouptype): uSet.add(v) else: uSet.add(v) closure(uSet, wSet, aSet) def test_tokenGroupsGlobalAndUniversal_manual(self): # Manually run the tokenGroups algorithm from MS-ADTS 3.1.1.4.5.19 and MS-DRSR 4.1.8.3 # and compare the result # The variable names come from MS-ADTS May 15, 2014 S = set() S.add(self.test_user_dn.get_casefold()) self.filtered_closure(S, GTYPE_SECURITY_GLOBAL_GROUP) T = set() # Not really a SID, we do this on DNs... for sid in S: X = set() X.add(sid) self.filtered_closure(X, GTYPE_SECURITY_UNIVERSAL_GROUP) T = T.union(X) T.remove(self.test_user_dn.get_casefold()) tokenGroupsSet = set() res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["tokenGroupsGlobalAndUniversal"]) self.assertEquals(len(res), 1) dn_tokengroups = [] for sid in res[0]['tokenGroupsGlobalAndUniversal']: sid = ndr_unpack(samba.dcerpc.security.dom_sid, sid) res3 = self.admin_ldb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE, attrs=[]) tokenGroupsSet.add(res3[0].dn.get_casefold()) if len(T.difference(tokenGroupsSet)): self.fail(msg="additional calculated: %s" % T.difference(tokenGroupsSet)) if len(tokenGroupsSet.difference(T)): self.fail(msg="additional tokenGroupsGlobalAndUniversal: %s" % tokenGroupsSet.difference(T))
class DynamicTokenTest(samba.tests.TestCase): def get_creds(self, target_username, target_password): creds_tmp = Credentials() creds_tmp.set_username(target_username) creds_tmp.set_password(target_password) creds_tmp.set_domain(creds.get_domain()) creds_tmp.set_realm(creds.get_realm()) creds_tmp.set_workstation(creds.get_workstation()) creds_tmp.set_gensec_features(creds_tmp.get_gensec_features() | gensec.FEATURE_SEAL) return creds_tmp def get_ldb_connection(self, target_username, target_password): creds_tmp = self.get_creds(target_username, target_password) ldb_target = SamDB(url=url, credentials=creds_tmp, lp=lp) return ldb_target def setUp(self): super(DynamicTokenTest, self).setUp() self.admin_ldb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp) self.base_dn = self.admin_ldb.domain_dn() self.test_user = "******" self.test_user_pass = "******" self.admin_ldb.newuser(self.test_user, self.test_user_pass) self.test_group0 = "tokengroups_group0" self.admin_ldb.newgroup( self.test_group0, grouptype=dsdb.GTYPE_SECURITY_DOMAIN_LOCAL_GROUP) res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group0, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE) self.test_group0_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group0, [self.test_user], add_members_operation=True) self.test_group1 = "tokengroups_group1" self.admin_ldb.newgroup(self.test_group1, grouptype=dsdb.GTYPE_SECURITY_GLOBAL_GROUP) res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group1, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE) self.test_group1_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group1, [self.test_user], add_members_operation=True) self.test_group2 = "tokengroups_group2" self.admin_ldb.newgroup(self.test_group2, grouptype=dsdb.GTYPE_SECURITY_UNIVERSAL_GROUP) res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group2, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE) self.test_group2_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group2, [self.test_user], add_members_operation=True) self.test_group3 = "tokengroups_group3" self.admin_ldb.newgroup(self.test_group3, grouptype=dsdb.GTYPE_SECURITY_UNIVERSAL_GROUP) res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group3, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE) self.test_group3_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group3, [self.test_group1], add_members_operation=True) self.test_group4 = "tokengroups_group4" self.admin_ldb.newgroup(self.test_group4, grouptype=dsdb.GTYPE_SECURITY_UNIVERSAL_GROUP) res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group4, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE) self.test_group4_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group4, [self.test_group3], add_members_operation=True) self.test_group5 = "tokengroups_group5" self.admin_ldb.newgroup( self.test_group5, grouptype=dsdb.GTYPE_SECURITY_DOMAIN_LOCAL_GROUP) res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group5, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE) self.test_group5_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group5, [self.test_group4], add_members_operation=True) self.test_group6 = "tokengroups_group6" self.admin_ldb.newgroup( self.test_group6, grouptype=dsdb.GTYPE_SECURITY_DOMAIN_LOCAL_GROUP) res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group6, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE) self.test_group6_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group6, [self.test_user], add_members_operation=True) self.ldb = self.get_ldb_connection(self.test_user, self.test_user_pass) res = self.ldb.search("", scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) self.assertEquals(len(res), 1) self.user_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["tokenGroups"][0]) self.user_sid_dn = "<SID=%s>" % str(self.user_sid) res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=[]) self.assertEquals(len(res), 1) self.test_user_dn = res[0].dn session_info_flags = (AUTH_SESSION_INFO_DEFAULT_GROUPS | AUTH_SESSION_INFO_AUTHENTICATED | AUTH_SESSION_INFO_SIMPLE_PRIVILEGES) if creds.get_kerberos_state() == DONT_USE_KERBEROS: session_info_flags |= AUTH_SESSION_INFO_NTLM session = samba.auth.user_session( self.ldb, lp_ctx=lp, dn=self.user_sid_dn, session_info_flags=session_info_flags) token = session.security_token self.user_sids = [] for s in token.sids: self.user_sids.append(str(s)) def tearDown(self): super(DynamicTokenTest, self).tearDown() delete_force( self.admin_ldb, "CN=%s,%s,%s" % (self.test_user, "cn=users", self.base_dn)) delete_force( self.admin_ldb, "CN=%s,%s,%s" % (self.test_group0, "cn=users", self.base_dn)) delete_force( self.admin_ldb, "CN=%s,%s,%s" % (self.test_group1, "cn=users", self.base_dn)) delete_force( self.admin_ldb, "CN=%s,%s,%s" % (self.test_group2, "cn=users", self.base_dn)) delete_force( self.admin_ldb, "CN=%s,%s,%s" % (self.test_group3, "cn=users", self.base_dn)) delete_force( self.admin_ldb, "CN=%s,%s,%s" % (self.test_group4, "cn=users", self.base_dn)) delete_force( self.admin_ldb, "CN=%s,%s,%s" % (self.test_group5, "cn=users", self.base_dn)) delete_force( self.admin_ldb, "CN=%s,%s,%s" % (self.test_group6, "cn=users", self.base_dn)) def test_rootDSE_tokenGroups(self): """Testing rootDSE tokengroups against internal calculation""" if not url.startswith("ldap"): self.fail(msg="This test is only valid on ldap") res = self.ldb.search("", scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) self.assertEquals(len(res), 1) print("Getting tokenGroups from rootDSE") tokengroups = [] for sid in res[0]['tokenGroups']: tokengroups.append( str(ndr_unpack(samba.dcerpc.security.dom_sid, sid))) sidset1 = set(tokengroups) sidset2 = set(self.user_sids) if len(sidset1.difference(sidset2)): print("token sids don't match") print("tokengroups: %s" % tokengroups) print("calculated : %s" % self.user_sids) print("difference : %s" % sidset1.difference(sidset2)) self.fail( msg="calculated groups don't match against rootDSE tokenGroups" ) def test_dn_tokenGroups(self): print("Getting tokenGroups from user DN") res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) self.assertEquals(len(res), 1) dn_tokengroups = [] for sid in res[0]['tokenGroups']: dn_tokengroups.append( str(ndr_unpack(samba.dcerpc.security.dom_sid, sid))) sidset1 = set(dn_tokengroups) sidset2 = set(self.user_sids) # The SIDs on the DN do not include the NTLM authentication SID sidset2.discard(samba.dcerpc.security.SID_NT_NTLM_AUTHENTICATION) if len(sidset1.difference(sidset2)): print("token sids don't match") print("difference : %s" % sidset1.difference(sidset2)) self.fail( msg="calculated groups don't match against user DN tokenGroups" ) def test_pac_groups(self): settings = {} settings["lp_ctx"] = lp settings["target_hostname"] = lp.get("netbios name") gensec_client = gensec.Security.start_client(settings) gensec_client.set_credentials( self.get_creds(self.test_user, self.test_user_pass)) gensec_client.want_feature(gensec.FEATURE_SEAL) gensec_client.start_mech_by_sasl_name("GSSAPI") auth_context = AuthContext(lp_ctx=lp, ldb=self.ldb, methods=[]) gensec_server = gensec.Security.start_server(settings, auth_context) machine_creds = Credentials() machine_creds.guess(lp) machine_creds.set_machine_account(lp) gensec_server.set_credentials(machine_creds) gensec_server.want_feature(gensec.FEATURE_SEAL) gensec_server.start_mech_by_sasl_name("GSSAPI") client_finished = False server_finished = False server_to_client = "" # Run the actual call loop. while client_finished == False and server_finished == False: if not client_finished: print "running client gensec_update" (client_finished, client_to_server) = gensec_client.update(server_to_client) if not server_finished: print "running server gensec_update" (server_finished, server_to_client) = gensec_server.update(client_to_server) session = gensec_server.session_info() token = session.security_token pac_sids = [] for s in token.sids: pac_sids.append(str(s)) sidset1 = set(pac_sids) sidset2 = set(self.user_sids) if len(sidset1.difference(sidset2)): print("token sids don't match") print("difference : %s" % sidset1.difference(sidset2)) self.fail( msg="calculated groups don't match against user PAC tokenGroups" ) def test_tokenGroups_manual(self): # Manually run the tokenGroups algorithm from MS-ADTS 3.1.1.4.5.19 and MS-DRSR 4.1.8.3 # and compare the result res = self.admin_ldb.search( base=self.base_dn, scope=ldb.SCOPE_SUBTREE, expression="(|(objectclass=user)(objectclass=group))", attrs=["memberOf"]) aSet = set() aSetR = set() vSet = set() for obj in res: if "memberOf" in obj: for dn in obj["memberOf"]: first = obj.dn.get_casefold() second = ldb.Dn(self.admin_ldb, dn).get_casefold() aSet.add((first, second)) aSetR.add((second, first)) vSet.add(first) vSet.add(second) res = self.admin_ldb.search(base=self.base_dn, scope=ldb.SCOPE_SUBTREE, expression="(objectclass=user)", attrs=["primaryGroupID"]) for obj in res: if "primaryGroupID" in obj: sid = "%s-%d" % (self.admin_ldb.get_domain_sid(), int(obj["primaryGroupID"][0])) res2 = self.admin_ldb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE, attrs=[]) first = obj.dn.get_casefold() second = res2[0].dn.get_casefold() aSet.add((first, second)) aSetR.add((second, first)) vSet.add(first) vSet.add(second) wSet = set() wSet.add(self.test_user_dn.get_casefold()) closure(vSet, wSet, aSet) wSet.remove(self.test_user_dn.get_casefold()) tokenGroupsSet = set() res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) self.assertEquals(len(res), 1) dn_tokengroups = [] for sid in res[0]['tokenGroups']: sid = ndr_unpack(samba.dcerpc.security.dom_sid, sid) res3 = self.admin_ldb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE, attrs=[]) tokenGroupsSet.add(res3[0].dn.get_casefold()) if len(wSet.difference(tokenGroupsSet)): self.fail(msg="additional calculated: %s" % wSet.difference(tokenGroupsSet)) if len(tokenGroupsSet.difference(wSet)): self.fail(msg="additional tokenGroups: %s" % tokenGroupsSet.difference(wSet)) def filtered_closure(self, wSet, filter_grouptype): res = self.admin_ldb.search( base=self.base_dn, scope=ldb.SCOPE_SUBTREE, expression="(|(objectclass=user)(objectclass=group))", attrs=["memberOf"]) aSet = set() aSetR = set() vSet = set() for obj in res: vSet.add(obj.dn.get_casefold()) if "memberOf" in obj: for dn in obj["memberOf"]: first = obj.dn.get_casefold() second = ldb.Dn(self.admin_ldb, dn).get_casefold() aSet.add((first, second)) aSetR.add((second, first)) vSet.add(first) vSet.add(second) res = self.admin_ldb.search(base=self.base_dn, scope=ldb.SCOPE_SUBTREE, expression="(objectclass=user)", attrs=["primaryGroupID"]) for obj in res: if "primaryGroupID" in obj: sid = "%s-%d" % (self.admin_ldb.get_domain_sid(), int(obj["primaryGroupID"][0])) res2 = self.admin_ldb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE, attrs=[]) first = obj.dn.get_casefold() second = res2[0].dn.get_casefold() aSet.add((first, second)) aSetR.add((second, first)) vSet.add(first) vSet.add(second) uSet = set() for v in vSet: res_group = self.admin_ldb.search(base=v, scope=ldb.SCOPE_BASE, attrs=["groupType"], expression="objectClass=group") if len(res_group) == 1: if hex(int(res_group[0]["groupType"][0]) & 0x00000000FFFFFFFF) == hex(filter_grouptype): uSet.add(v) else: uSet.add(v) closure(uSet, wSet, aSet) def test_tokenGroupsGlobalAndUniversal_manual(self): # Manually run the tokenGroups algorithm from MS-ADTS 3.1.1.4.5.19 and MS-DRSR 4.1.8.3 # and compare the result # The variable names come from MS-ADTS May 15, 2014 S = set() S.add(self.test_user_dn.get_casefold()) self.filtered_closure(S, GTYPE_SECURITY_GLOBAL_GROUP) T = set() # Not really a SID, we do this on DNs... for sid in S: X = set() X.add(sid) self.filtered_closure(X, GTYPE_SECURITY_UNIVERSAL_GROUP) T = T.union(X) T.remove(self.test_user_dn.get_casefold()) tokenGroupsSet = set() res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["tokenGroupsGlobalAndUniversal"]) self.assertEquals(len(res), 1) dn_tokengroups = [] for sid in res[0]['tokenGroupsGlobalAndUniversal']: sid = ndr_unpack(samba.dcerpc.security.dom_sid, sid) res3 = self.admin_ldb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE, attrs=[]) tokenGroupsSet.add(res3[0].dn.get_casefold()) if len(T.difference(tokenGroupsSet)): self.fail(msg="additional calculated: %s" % T.difference(tokenGroupsSet)) if len(tokenGroupsSet.difference(T)): self.fail(msg="additional tokenGroupsGlobalAndUniversal: %s" % tokenGroupsSet.difference(T)) def test_samr_GetGroupsForUser(self): # Confirm that we get the correct results against SAMR also if not url.startswith("ldap://"): self.fail( msg= "This test is only valid on ldap (so we an find the hostname and use SAMR)" ) host = url.split("://")[1] (domain_sid, user_rid) = self.user_sid.split() samr_conn = samba.dcerpc.samr.samr("ncacn_ip_tcp:%s[seal]" % host, lp, creds) samr_handle = samr_conn.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED) samr_domain = samr_conn.OpenDomain(samr_handle, security.SEC_FLAG_MAXIMUM_ALLOWED, domain_sid) user_handle = samr_conn.OpenUser(samr_domain, security.SEC_FLAG_MAXIMUM_ALLOWED, user_rid) rids = samr_conn.GetGroupsForUser(user_handle) samr_dns = set() for rid in rids.rids: self.assertEqual( rid.attributes, samr.SE_GROUP_MANDATORY | samr.SE_GROUP_ENABLED_BY_DEFAULT | samr.SE_GROUP_ENABLED) sid = "%s-%d" % (domain_sid, rid.rid) res = self.admin_ldb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE, attrs=[]) samr_dns.add(res[0].dn.get_casefold()) user_info = samr_conn.QueryUserInfo(user_handle, 1) self.assertEqual(rids.rids[0].rid, user_info.primary_gid) tokenGroupsSet = set() res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["tokenGroupsGlobalAndUniversal"]) for sid in res[0]['tokenGroupsGlobalAndUniversal']: sid = ndr_unpack(samba.dcerpc.security.dom_sid, sid) res3 = self.admin_ldb.search( base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE, attrs=[], expression= "(&(|(grouptype=%d)(grouptype=%d))(objectclass=group))" % (GTYPE_SECURITY_GLOBAL_GROUP, GTYPE_SECURITY_UNIVERSAL_GROUP)) if len(res) == 1: tokenGroupsSet.add(res3[0].dn.get_casefold()) if len(samr_dns.difference(tokenGroupsSet)): self.fail( msg="additional samr_GetUserGroups over tokenGroups: %s" % samr_dns.difference(tokenGroupsSet)) memberOf = set() # Add the primary group primary_group_sid = "%s-%d" % (domain_sid, user_info.primary_gid) res2 = self.admin_ldb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE, attrs=[]) memberOf.add(res2[0].dn.get_casefold()) res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["memberOf"]) for dn in res[0]['memberOf']: res3 = self.admin_ldb.search( base=dn, scope=ldb.SCOPE_BASE, attrs=[], expression= "(&(|(grouptype=%d)(grouptype=%d))(objectclass=group))" % (GTYPE_SECURITY_GLOBAL_GROUP, GTYPE_SECURITY_UNIVERSAL_GROUP)) if len(res3) == 1: memberOf.add(res3[0].dn.get_casefold()) if len(memberOf.difference(samr_dns)): self.fail(msg="additional memberOf over samr_GetUserGroups: %s" % memberOf.difference(samr_dns)) if len(samr_dns.difference(memberOf)): self.fail(msg="additional samr_GetUserGroups over memberOf: %s" % samr_dns.difference(memberOf)) S = set() S.add(self.test_user_dn.get_casefold()) self.filtered_closure(S, GTYPE_SECURITY_GLOBAL_GROUP) self.filtered_closure(S, GTYPE_SECURITY_UNIVERSAL_GROUP) # Now remove the user DN and primary group S.remove(self.test_user_dn.get_casefold()) if len(samr_dns.difference(S)): self.fail( msg="additional samr_GetUserGroups over filtered_closure: %s" % samr_dns.difference(S)) def test_samr_GetGroupsForUser_nomember(self): # Confirm that we get the correct results against SAMR also if not url.startswith("ldap://"): self.fail( msg= "This test is only valid on ldap (so we an find the hostname and use SAMR)" ) host = url.split("://")[1] test_user = "******" self.admin_ldb.newuser(test_user, self.test_user_pass) res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (test_user, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE) user_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) (domain_sid, user_rid) = user_sid.split() samr_conn = samba.dcerpc.samr.samr("ncacn_ip_tcp:%s[seal]" % host, lp, creds) samr_handle = samr_conn.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED) samr_domain = samr_conn.OpenDomain(samr_handle, security.SEC_FLAG_MAXIMUM_ALLOWED, domain_sid) user_handle = samr_conn.OpenUser(samr_domain, security.SEC_FLAG_MAXIMUM_ALLOWED, user_rid) rids = samr_conn.GetGroupsForUser(user_handle) user_info = samr_conn.QueryUserInfo(user_handle, 1) delete_force(self.admin_ldb, "CN=%s,%s,%s" % (test_user, "cn=users", self.base_dn)) self.assertEqual(len(rids.rids), 1) self.assertEqual(rids.rids[0].rid, user_info.primary_gid)
class DynamicTokenTest(samba.tests.TestCase): def get_creds(self, target_username, target_password): creds_tmp = Credentials() creds_tmp.set_username(target_username) creds_tmp.set_password(target_password) creds_tmp.set_domain(creds.get_domain()) creds_tmp.set_realm(creds.get_realm()) creds_tmp.set_workstation(creds.get_workstation()) creds_tmp.set_gensec_features(creds_tmp.get_gensec_features() | gensec.FEATURE_SEAL) return creds_tmp def get_ldb_connection(self, target_username, target_password): creds_tmp = self.get_creds(target_username, target_password) ldb_target = SamDB(url=url, credentials=creds_tmp, lp=lp) return ldb_target def setUp(self): super(DynamicTokenTest, self).setUp() self.admin_ldb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp) self.base_dn = self.admin_ldb.domain_dn() self.test_user = "******" self.test_user_pass = "******" self.admin_ldb.newuser(self.test_user, self.test_user_pass) self.test_group0 = "tokengroups_group0" self.admin_ldb.newgroup(self.test_group0, grouptype=dsdb.GTYPE_SECURITY_DOMAIN_LOCAL_GROUP) res = self.admin_ldb.search( base="cn={0!s},cn=users,{1!s}".format(self.test_group0, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE, ) self.test_group0_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group0, [self.test_user], add_members_operation=True) self.test_group1 = "tokengroups_group1" self.admin_ldb.newgroup(self.test_group1, grouptype=dsdb.GTYPE_SECURITY_GLOBAL_GROUP) res = self.admin_ldb.search( base="cn={0!s},cn=users,{1!s}".format(self.test_group1, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE, ) self.test_group1_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group1, [self.test_user], add_members_operation=True) self.test_group2 = "tokengroups_group2" self.admin_ldb.newgroup(self.test_group2, grouptype=dsdb.GTYPE_SECURITY_UNIVERSAL_GROUP) res = self.admin_ldb.search( base="cn={0!s},cn=users,{1!s}".format(self.test_group2, self.base_dn), attrs=["objectSid"], scope=ldb.SCOPE_BASE, ) self.test_group2_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0]) self.admin_ldb.add_remove_group_members(self.test_group2, [self.test_user], add_members_operation=True) self.ldb = self.get_ldb_connection(self.test_user, self.test_user_pass) res = self.ldb.search("", scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) self.assertEquals(len(res), 1) self.user_sid_dn = "<SID={0!s}>".format( str(ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["tokenGroups"][0])) ) res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=[]) self.assertEquals(len(res), 1) self.test_user_dn = res[0].dn session_info_flags = ( AUTH_SESSION_INFO_DEFAULT_GROUPS | AUTH_SESSION_INFO_AUTHENTICATED | AUTH_SESSION_INFO_SIMPLE_PRIVILEGES ) session = samba.auth.user_session( self.ldb, lp_ctx=lp, dn=self.user_sid_dn, session_info_flags=session_info_flags ) token = session.security_token self.user_sids = [] for s in token.sids: self.user_sids.append(str(s)) def tearDown(self): super(DynamicTokenTest, self).tearDown() delete_force(self.admin_ldb, "CN={0!s},{1!s},{2!s}".format(self.test_user, "cn=users", self.base_dn)) delete_force(self.admin_ldb, "CN={0!s},{1!s},{2!s}".format(self.test_group0, "cn=users", self.base_dn)) delete_force(self.admin_ldb, "CN={0!s},{1!s},{2!s}".format(self.test_group1, "cn=users", self.base_dn)) delete_force(self.admin_ldb, "CN={0!s},{1!s},{2!s}".format(self.test_group2, "cn=users", self.base_dn)) def test_rootDSE_tokenGroups(self): """Testing rootDSE tokengroups against internal calculation""" if not url.startswith("ldap"): self.fail(msg="This test is only valid on ldap") res = self.ldb.search("", scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) self.assertEquals(len(res), 1) print ("Getting tokenGroups from rootDSE") tokengroups = [] for sid in res[0]["tokenGroups"]: tokengroups.append(str(ndr_unpack(samba.dcerpc.security.dom_sid, sid))) sidset1 = set(tokengroups) sidset2 = set(self.user_sids) if len(sidset1.difference(sidset2)): print ("token sids don't match") print ("tokengroups: {0!s}".format(tokengroups)) print ("calculated : {0!s}".format(self.user_sids)) print ("difference : {0!s}".format(sidset1.difference(sidset2))) self.fail(msg="calculated groups don't match against rootDSE tokenGroups") def test_dn_tokenGroups(self): print ("Getting tokenGroups from user DN") res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) self.assertEquals(len(res), 1) dn_tokengroups = [] for sid in res[0]["tokenGroups"]: dn_tokengroups.append(str(ndr_unpack(samba.dcerpc.security.dom_sid, sid))) sidset1 = set(dn_tokengroups) sidset2 = set(self.user_sids) if len(sidset1.difference(sidset2)): print ("token sids don't match") print ("difference : {0!s}".format(sidset1.difference(sidset2))) self.fail(msg="calculated groups don't match against user DN tokenGroups") def test_pac_groups(self): settings = {} settings["lp_ctx"] = lp settings["target_hostname"] = lp.get("netbios name") gensec_client = gensec.Security.start_client(settings) gensec_client.set_credentials(self.get_creds(self.test_user, self.test_user_pass)) gensec_client.want_feature(gensec.FEATURE_SEAL) gensec_client.start_mech_by_sasl_name("GSSAPI") auth_context = AuthContext(lp_ctx=lp, ldb=self.ldb, methods=[]) gensec_server = gensec.Security.start_server(settings, auth_context) machine_creds = Credentials() machine_creds.guess(lp) machine_creds.set_machine_account(lp) gensec_server.set_credentials(machine_creds) gensec_server.want_feature(gensec.FEATURE_SEAL) gensec_server.start_mech_by_sasl_name("GSSAPI") client_finished = False server_finished = False server_to_client = "" # Run the actual call loop. while client_finished == False and server_finished == False: if not client_finished: print "running client gensec_update" (client_finished, client_to_server) = gensec_client.update(server_to_client) if not server_finished: print "running server gensec_update" (server_finished, server_to_client) = gensec_server.update(client_to_server) session = gensec_server.session_info() token = session.security_token pac_sids = [] for s in token.sids: pac_sids.append(str(s)) sidset1 = set(pac_sids) sidset2 = set(self.user_sids) if len(sidset1.difference(sidset2)): print ("token sids don't match") print ("difference : {0!s}".format(sidset1.difference(sidset2))) self.fail(msg="calculated groups don't match against user PAC tokenGroups") def test_tokenGroups_manual(self): # Manually run the tokenGroups algorithm from MS-ADTS 3.1.1.4.5.19 and MS-DRSR 4.1.8.3 # and compare the result res = self.admin_ldb.search( base=self.base_dn, scope=ldb.SCOPE_SUBTREE, expression="(|(objectclass=user)(objectclass=group))", attrs=["memberOf"], ) aSet = set() aSetR = set() vSet = set() for obj in res: if "memberOf" in obj: for dn in obj["memberOf"]: first = obj.dn.get_casefold() second = ldb.Dn(self.admin_ldb, dn).get_casefold() aSet.add((first, second)) aSetR.add((second, first)) vSet.add(first) vSet.add(second) res = self.admin_ldb.search( base=self.base_dn, scope=ldb.SCOPE_SUBTREE, expression="(objectclass=user)", attrs=["primaryGroupID"] ) for obj in res: if "primaryGroupID" in obj: sid = "{0!s}-{1:d}".format(self.admin_ldb.get_domain_sid(), int(obj["primaryGroupID"][0])) res2 = self.admin_ldb.search(base="<SID={0!s}>".format(sid), scope=ldb.SCOPE_BASE, attrs=[]) first = obj.dn.get_casefold() second = res2[0].dn.get_casefold() aSet.add((first, second)) aSetR.add((second, first)) vSet.add(first) vSet.add(second) wSet = set() wSet.add(self.test_user_dn.get_casefold()) closure(vSet, wSet, aSet) wSet.remove(self.test_user_dn.get_casefold()) tokenGroupsSet = set() res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) self.assertEquals(len(res), 1) dn_tokengroups = [] for sid in res[0]["tokenGroups"]: sid = ndr_unpack(samba.dcerpc.security.dom_sid, sid) res3 = self.admin_ldb.search(base="<SID={0!s}>".format(sid), scope=ldb.SCOPE_BASE, attrs=[]) tokenGroupsSet.add(res3[0].dn.get_casefold()) if len(wSet.difference(tokenGroupsSet)): self.fail(msg="additional calculated: {0!s}".format(wSet.difference(tokenGroupsSet))) if len(tokenGroupsSet.difference(wSet)): self.fail(msg="additional tokenGroups: {0!s}".format(tokenGroupsSet.difference(wSet))) def filtered_closure(self, wSet, filter_grouptype): res = self.admin_ldb.search( base=self.base_dn, scope=ldb.SCOPE_SUBTREE, expression="(|(objectclass=user)(objectclass=group))", attrs=["memberOf"], ) aSet = set() aSetR = set() vSet = set() for obj in res: vSet.add(obj.dn.get_casefold()) if "memberOf" in obj: for dn in obj["memberOf"]: first = obj.dn.get_casefold() second = ldb.Dn(self.admin_ldb, dn).get_casefold() aSet.add((first, second)) aSetR.add((second, first)) vSet.add(first) vSet.add(second) res = self.admin_ldb.search( base=self.base_dn, scope=ldb.SCOPE_SUBTREE, expression="(objectclass=user)", attrs=["primaryGroupID"] ) for obj in res: if "primaryGroupID" in obj: sid = "{0!s}-{1:d}".format(self.admin_ldb.get_domain_sid(), int(obj["primaryGroupID"][0])) res2 = self.admin_ldb.search(base="<SID={0!s}>".format(sid), scope=ldb.SCOPE_BASE, attrs=[]) first = obj.dn.get_casefold() second = res2[0].dn.get_casefold() aSet.add((first, second)) aSetR.add((second, first)) vSet.add(first) vSet.add(second) uSet = set() for v in vSet: res_group = self.admin_ldb.search( base=v, scope=ldb.SCOPE_BASE, attrs=["groupType"], expression="objectClass=group" ) if len(res_group) == 1: if hex(int(res_group[0]["groupType"][0]) & 0x00000000FFFFFFFF) == hex(filter_grouptype): uSet.add(v) else: uSet.add(v) closure(uSet, wSet, aSet) def test_tokenGroupsGlobalAndUniversal_manual(self): # Manually run the tokenGroups algorithm from MS-ADTS 3.1.1.4.5.19 and MS-DRSR 4.1.8.3 # and compare the result # The variable names come from MS-ADTS May 15, 2014 S = set() S.add(self.test_user_dn.get_casefold()) self.filtered_closure(S, GTYPE_SECURITY_GLOBAL_GROUP) T = set() # Not really a SID, we do this on DNs... for sid in S: X = set() X.add(sid) self.filtered_closure(X, GTYPE_SECURITY_UNIVERSAL_GROUP) T = T.union(X) T.remove(self.test_user_dn.get_casefold()) tokenGroupsSet = set() res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["tokenGroupsGlobalAndUniversal"]) self.assertEquals(len(res), 1) dn_tokengroups = [] for sid in res[0]["tokenGroupsGlobalAndUniversal"]: sid = ndr_unpack(samba.dcerpc.security.dom_sid, sid) res3 = self.admin_ldb.search(base="<SID={0!s}>".format(sid), scope=ldb.SCOPE_BASE, attrs=[]) tokenGroupsSet.add(res3[0].dn.get_casefold()) if len(T.difference(tokenGroupsSet)): self.fail(msg="additional calculated: {0!s}".format(T.difference(tokenGroupsSet))) if len(tokenGroupsSet.difference(T)): self.fail(msg="additional tokenGroupsGlobalAndUniversal: {0!s}".format(tokenGroupsSet.difference(T)))