sys.path.append("bin/python")
import samba
-samba.ensure_external_module("subunit", "subunit/python")
samba.ensure_external_module("testtools", "testtools")
+samba.ensure_external_module("subunit", "subunit/python")
import samba.getopt as options
from ldb import ERR_NO_SUCH_OBJECT, ERR_ATTRIBUTE_OR_VALUE_EXISTS
from ldb import ERR_ENTRY_ALREADY_EXISTS, ERR_UNWILLING_TO_PERFORM
from ldb import ERR_NOT_ALLOWED_ON_NON_LEAF, ERR_OTHER, ERR_INVALID_DN_SYNTAX
-from ldb import ERR_NO_SUCH_ATTRIBUTE
+from ldb import ERR_NO_SUCH_ATTRIBUTE, ERR_INVALID_ATTRIBUTE_SYNTAX
from ldb import ERR_OBJECT_CLASS_VIOLATION, ERR_NOT_ALLOWED_ON_RDN
from ldb import ERR_NAMING_VIOLATION, ERR_CONSTRAINT_VIOLATION
-from ldb import ERR_UNDEFINED_ATTRIBUTE_TYPE
from ldb import Message, MessageElement, Dn
from ldb import FLAG_MOD_ADD, FLAG_MOD_REPLACE, FLAG_MOD_DELETE
+from ldb import timestring
from samba import Ldb
-from samba.dsdb import (UF_NORMAL_ACCOUNT, UF_INTERDOMAIN_TRUST_ACCOUNT,
- UF_WORKSTATION_TRUST_ACCOUNT, UF_SERVER_TRUST_ACCOUNT,
- UF_PARTIAL_SECRETS_ACCOUNT,
+from samba.dsdb import (UF_NORMAL_ACCOUNT,
+ UF_WORKSTATION_TRUST_ACCOUNT,
UF_PASSWD_NOTREQD, UF_ACCOUNTDISABLE, ATYPE_NORMAL_ACCOUNT,
- ATYPE_WORKSTATION_TRUST, SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE)
-from samba.dcerpc.security import (DOMAIN_RID_USERS, DOMAIN_RID_DOMAIN_MEMBERS,
- DOMAIN_RID_DCS, DOMAIN_RID_READONLY_DCS)
+ ATYPE_WORKSTATION_TRUST, SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE,
+ SYSTEM_FLAG_CONFIG_ALLOW_RENAME, SYSTEM_FLAG_CONFIG_ALLOW_MOVE,
+ SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE)
from subunit.run import SubunitTestRunner
import unittest
from samba.ndr import ndr_pack, ndr_unpack
from samba.dcerpc import security
-parser = optparse.OptionParser("ldap [options] <host>")
+parser = optparse.OptionParser("ldap.py [options] <host>")
sambaopts = options.SambaOptions(parser)
parser.add_option_group(sambaopts)
parser.add_option_group(options.VersionOptions(parser))
res = self.ldb.search(base=self.base_dn, expression="(objectClass=*)", scope=SCOPE_BASE)
return ndr_unpack( security.dom_sid,res[0]["objectSid"][0])
+ def set_dsheuristics(self, dsheuristics):
+ m = Message()
+ m.dn = Dn(self.ldb, "CN=Directory Service, CN=Windows NT, CN=Services, "
+ + self.configuration_dn)
+ if dsheuristics is not None:
+ m["dSHeuristics"] = MessageElement(dsheuristics, FLAG_MOD_REPLACE,
+ "dSHeuristics")
+ else:
+ m["dSHeuristics"] = MessageElement([], FLAG_MOD_DELETE, "dsHeuristics")
+ self.ldb.modify(m)
+
def setUp(self):
super(BasicTests, self).setUp()
self.ldb = ldb
self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
self.delete_force(self.ldb, "cn=ldaptestutf8user èùéìòà,cn=users," + self.base_dn)
self.delete_force(self.ldb, "cn=ldaptestutf8user2 èùéìòà,cn=users," + self.base_dn)
- self.delete_force(self.ldb, "cn=entry1,cn=ldaptestcontainer," + self.base_dn)
- self.delete_force(self.ldb, "cn=entry2,cn=ldaptestcontainer," + self.base_dn)
self.delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
self.delete_force(self.ldb, "cn=ldaptestcontainer2," + self.base_dn)
self.delete_force(self.ldb, "cn=parentguidtest,cn=users," + self.base_dn)
except LdbError, (num, _):
self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+ # Invalid objectclass specified
+ try:
+ self.ldb.add({
+ "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
+ "objectClass": [] })
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+
# Invalid objectclass specified
try:
self.ldb.add({
except LdbError, (num, _):
self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+ # Test allowed system flags
+ self.ldb.add({
+ "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
+ "objectClass": "person",
+ "systemFlags": str(~(SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_MOVE | SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE)) })
+
+ res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
+ scope=SCOPE_BASE, attrs=["systemFlags"])
+ self.assertTrue(len(res) == 1)
+ self.assertEquals(res[0]["systemFlags"][0], "0")
+
+ self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
+
self.ldb.add({
"dn": "cn=ldaptestuser,cn=users," + self.base_dn,
"objectClass": "person" })
except LdbError, (num, _):
self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
+ # We cannot remove all object classes by an empty replace
+ m = Message()
+ m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
+ m["objectClass"] = MessageElement([], FLAG_MOD_REPLACE, "objectClass")
+ try:
+ ldb.modify(m)
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
+
m = Message()
m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
m["objectClass"] = MessageElement(["top", "computer"], FLAG_MOD_REPLACE,
"objectClass")
ldb.modify(m)
- self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
+ self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
def test_system_only(self):
"""Test systemOnly objects"""
except LdbError, (num, _):
self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+ try:
+ self.ldb.add({
+ "dn": "cn=testsecret,cn=system," + self.base_dn,
+ "objectclass": "secret"})
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+
self.delete_force(self.ldb, "cn=ldaptestobject," + self.base_dn)
self.delete_force(self.ldb, "cn=testsecret,cn=system," + self.base_dn)
+ try:
+ self.ldb.add({
+ "dn": "cn=ldaptestcontainer," + self.base_dn,
+ "objectclass": "container",
+ "isCriticalSystemObject": "TRUE"})
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+
+ self.ldb.add({
+ "dn": "cn=ldaptestcontainer," + self.base_dn,
+ "objectclass": "container"})
+
+ m = Message()
+ m.dn = Dn(ldb, "cn=ldaptestcontainer," + self.base_dn)
+ m["isCriticalSystemObject"] = MessageElement("TRUE", FLAG_MOD_REPLACE,
+ "isCriticalSystemObject")
+ try:
+ ldb.modify(m)
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+
+ self.delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
+
+ # Proof if DC SAM object has "isCriticalSystemObject" set
+ res = self.ldb.search("", scope=SCOPE_BASE, attrs=["serverName"])
+ self.assertTrue(len(res) == 1)
+ self.assertTrue("serverName" in res[0])
+ res = self.ldb.search(res[0]["serverName"][0], scope=SCOPE_BASE,
+ attrs=["serverReference"])
+ self.assertTrue(len(res) == 1)
+ self.assertTrue("serverReference" in res[0])
+ res = self.ldb.search(res[0]["serverReference"][0], scope=SCOPE_BASE,
+ attrs=["isCriticalSystemObject"])
+ self.assertTrue(len(res) == 1)
+ self.assertTrue("isCriticalSystemObject" in res[0])
+ self.assertEquals(res[0]["isCriticalSystemObject"][0], "TRUE")
+
def test_invalid_parent(self):
"""Test adding an object with invalid parent"""
print "Test adding an object with invalid parent"""
self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
- def test_multi_valued_attributes(self):
- """Test multi-valued attributes"""
- print "Test multi-valued attributes"""
-
-# TODO: In this test I added some special tests where I got very unusual
-# results back from a real AD. s4 doesn't match them and I've no idea how to
-# implement those error cases (maybe there exists a special trigger for
-# "description" attributes which handle them)
+ def test_description_attribute(self):
+ """Test description attribute"""
+ print "Test description attribute"""
self.ldb.add({
"dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
"objectclass": "group",
"description": "desc1"})
+ res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
+ scope=SCOPE_BASE, attrs=["description"])
+ self.assertTrue(len(res) == 1)
+ self.assertTrue("description" in res[0])
+ self.assertTrue(len(res[0]["description"]) == 1)
+ self.assertEquals(res[0]["description"][0], "desc1")
+
self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
self.ldb.add({
"objectclass": "group",
"description": ["desc1", "desc2"]})
-# m = Message()
-# m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
-# m["description"] = MessageElement(["desc1","desc2"], FLAG_MOD_REPLACE,
-# "description")
-# try:
-# ldb.modify(m)
-# self.fail()
-# except LdbError, (num, _):
-# self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
+ res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
+ scope=SCOPE_BASE, attrs=["description"])
+ self.assertTrue(len(res) == 1)
+ self.assertTrue("description" in res[0])
+ self.assertTrue(len(res[0]["description"]) == 2)
+ self.assertTrue(res[0]["description"][0] == "desc1" or
+ res[0]["description"][1] == "desc1")
+ self.assertTrue(res[0]["description"][0] == "desc2" or
+ res[0]["description"][1] == "desc2")
+
+ m = Message()
+ m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+ m["description"] = MessageElement(["desc1","desc2"], FLAG_MOD_REPLACE,
+ "description")
+ try:
+ ldb.modify(m)
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
+
+ m = Message()
+ m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+ m["description"] = MessageElement(["desc1","desc2"], FLAG_MOD_DELETE,
+ "description")
+ ldb.modify(m)
+
+ self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+
+ self.ldb.add({
+ "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
+ "objectclass": "group" })
m = Message()
m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
"description")
ldb.modify(m)
-# m = Message()
-# m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
-# m["description"] = MessageElement("desc3", FLAG_MOD_ADD,
-# "description")
-# try:
-# ldb.modify(m)
-# self.fail()
-# except LdbError, (num, _):
-# self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
+ res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
+ scope=SCOPE_BASE, attrs=["description"])
+ self.assertTrue(len(res) == 1)
+ self.assertTrue("description" in res[0])
+ self.assertTrue(len(res[0]["description"]) == 1)
+ self.assertEquals(res[0]["description"][0], "desc1")
+
+ self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+
+ self.ldb.add({
+ "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
+ "objectclass": "group",
+ "description": ["desc1", "desc2"]})
+
+ m = Message()
+ m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+ m["description"] = MessageElement("desc1", FLAG_MOD_REPLACE,
+ "description")
+ ldb.modify(m)
+
+ res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
+ scope=SCOPE_BASE, attrs=["description"])
+ self.assertTrue(len(res) == 1)
+ self.assertTrue("description" in res[0])
+ self.assertTrue(len(res[0]["description"]) == 1)
+ self.assertEquals(res[0]["description"][0], "desc1")
+
+ m = Message()
+ m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+ m["description"] = MessageElement("desc3", FLAG_MOD_ADD,
+ "description")
+ try:
+ ldb.modify(m)
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
m = Message()
m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
m["description"] = MessageElement("desc1", FLAG_MOD_DELETE,
"description")
ldb.modify(m)
+ res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
+ scope=SCOPE_BASE, attrs=["description"])
+ self.assertTrue(len(res) == 1)
+ self.assertFalse("description" in res[0])
-# m = Message()
-# m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
-# m["description"] = MessageElement(["desc1","desc2"], FLAG_MOD_REPLACE,
-# "description")
+ m = Message()
+ m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+ m["description"] = MessageElement(["desc1","desc2"], FLAG_MOD_REPLACE,
+ "description")
+ try:
+ ldb.modify(m)
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
+
+ m = Message()
+ m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+ m["description"] = MessageElement(["desc3", "desc4"], FLAG_MOD_ADD,
+ "description")
+ try:
+ ldb.modify(m)
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
+
+ m = Message()
+ m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+ m["description"] = MessageElement("desc1", FLAG_MOD_ADD,
+ "description")
+ ldb.modify(m)
+
+ res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
+ scope=SCOPE_BASE, attrs=["description"])
+ self.assertTrue(len(res) == 1)
+ self.assertTrue("description" in res[0])
+ self.assertTrue(len(res[0]["description"]) == 1)
+ self.assertEquals(res[0]["description"][0], "desc1")
+
+ self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+
+ def test_attribute_ranges(self):
+ """Test attribute ranges"""
+ print "Test attribute ranges"""
+
+ # Too short (min. 1)
+ try:
+ ldb.add({
+ "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
+ "objectClass": "person",
+ "sn": "" })
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_INVALID_ATTRIBUTE_SYNTAX)
+
+ # Too long (max. 64)
# try:
-# ldb.modify(m)
+# ldb.add({
+# "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
+# "objectClass": "person",
+# "sn": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" })
# self.fail()
# except LdbError, (num, _):
-# self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
+# self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+
+ ldb.add({
+ "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
+ "objectClass": "person" })
+
+ # Too short (min. 1)
+ m = Message()
+ m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
+ m["sn"] = MessageElement("", FLAG_MOD_REPLACE, "sn")
+ try:
+ ldb.modify(m)
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_INVALID_ATTRIBUTE_SYNTAX)
+ # Too long (max. 64)
# m = Message()
-# m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
-# m["description"] = MessageElement(["desc3", "desc4"], FLAG_MOD_ADD,
-# "description")
+# m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
+# m["sn"] = MessageElement("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", FLAG_MOD_REPLACE, "sn")
# try:
# ldb.modify(m)
# self.fail()
# except LdbError, (num, _):
-# self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
+# self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
m = Message()
- m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
- m["description"] = MessageElement("desc3", FLAG_MOD_ADD,
- "description")
+ m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
+ m["sn"] = MessageElement("x", FLAG_MOD_REPLACE, "sn")
ldb.modify(m)
- self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+ self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
def test_empty_messages(self):
"""Test empty messages"""
"""Tests the 'distinguishedName' attribute"""
print "Tests the 'distinguishedName' attribute"""
+ # The "dn" shortcut isn't supported
+ m = Message()
+ m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+ m["objectClass"] = MessageElement("group", 0, "objectClass")
+ m["dn"] = MessageElement("cn=ldaptestgroup,cn=users," + self.base_dn, 0,
+ "dn")
+ try:
+ ldb.add(m)
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
+
# a wrong "distinguishedName" attribute is obviously tolerated
self.ldb.add({
"dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
self.assertTrue(Dn(ldb, res[0]["distinguishedName"][0])
== Dn(ldb, "cn=ldaptestgroup, cn=users," + self.base_dn))
+ # The "dn" shortcut isn't supported
+ m = Message()
+ m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+ m["dn"] = MessageElement(
+ "cn=ldaptestgroup,cn=users," + self.base_dn, FLAG_MOD_REPLACE,
+ "dn")
+ try:
+ ldb.modify(m)
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
+
m = Message()
m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
m["distinguishedName"] = MessageElement(
self.ldb.add({
"dn": "cn=ldaptestuser2,cn=users," + self.base_dn,
- "objectclass": ["user", "person"] })
+ "objectclass": "user" })
ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser2,cn=users," + self.base_dn)
ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=users," + self.base_dn)
self.ldb.add({
"dn": "cn=ldaptestuser5,cn=users," + self.base_dn,
- "objectclass": ["user", "person"] })
+ "objectclass": "user" })
ldb.rename("cn=ldaptestuser5,cn=users," + self.base_dn, "cn=ldaptestUSER5,cn=users," + self.base_dn)
self.delete_force(self.ldb, "cn=ldaptestuser5,cn=users," + self.base_dn)
self.ldb.add({
"dn": "cn=ldaptestuser5,cn=users," + self.base_dn,
- "objectclass": ["user", "person"] })
+ "objectclass": "user" })
ldb.rename("cn=ldaptestuser5,cn=Users," + self.base_dn, "cn=ldaptestUSER5,cn=users," + self.base_dn)
res = ldb.search(expression="cn=ldaptestuser5")
print "Found %u records" % len(res)
self.assertEquals(len(res), 1, "Wrong number of hits for (&(cn=ldaptestuser5)(objectclass=user))")
self.delete_force(self.ldb, "cn=ldaptestuser5,cn=users," + self.base_dn)
+ def test_objectGUID(self):
+ """Test objectGUID behaviour"""
+ print "Testing objectGUID behaviour\n"
+
+ # The objectGUID cannot directly be set
+ try:
+ self.ldb.add_ldif("""
+dn: cn=ldaptestcontainer,""" + self.base_dn + """
+objectClass: container
+objectGUID: bd3480c9-58af-4cd8-92df-bc4a18b6e44d
+""")
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+
+ self.ldb.add({
+ "dn": "cn=ldaptestcontainer," + self.base_dn,
+ "objectClass": "container" })
+
+ res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
+ scope=SCOPE_BASE,
+ attrs=["objectGUID", "uSNCreated", "uSNChanged", "whenCreated", "whenChanged"])
+ self.assertTrue(len(res) == 1)
+ self.assertTrue("objectGUID" in res[0])
+ self.assertTrue("uSNCreated" in res[0])
+ self.assertTrue("uSNChanged" in res[0])
+ self.assertTrue("whenCreated" in res[0])
+ self.assertTrue("whenChanged" in res[0])
+
+ self.delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
+
+ # All the following attributes are specificable on add operations
+ self.ldb.add({
+ "dn": "cn=ldaptestcontainer," + self.base_dn,
+ "objectClass": "container",
+ "uSNCreated" : "1",
+ "uSNChanged" : "1",
+ "whenCreated": timestring(long(time.time())),
+ "whenChanged": timestring(long(time.time())) })
+
+ res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
+ scope=SCOPE_BASE,
+ attrs=["objectGUID", "uSNCreated", "uSNChanged", "whenCreated", "whenChanged"])
+ self.assertTrue(len(res) == 1)
+ self.assertTrue("objectGUID" in res[0])
+ self.assertTrue("uSNCreated" in res[0])
+ self.assertFalse(res[0]["uSNCreated"][0] == "1") # these are corrected
+ self.assertTrue("uSNChanged" in res[0])
+ self.assertFalse(res[0]["uSNChanged"][0] == "1") # these are corrected
+
+ self.delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
+
+ # All this attributes are specificable on add operations
+ self.ldb.add({
+ "dn": "cn=ldaptestcontainer," + self.base_dn,
+ "objectclass": "container",
+ "uSNCreated" : "1",
+ "uSNChanged" : "1",
+ "whenCreated": timestring(long(time.time())),
+ "whenChanged": timestring(long(time.time())) })
+
+ res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
+ scope=SCOPE_BASE,
+ attrs=["objectGUID", "uSNCreated", "uSNChanged", "whenCreated", "whenChanged"])
+ self.assertTrue(len(res) == 1)
+ self.assertTrue("objectGUID" in res[0])
+ self.assertTrue("uSNCreated" in res[0])
+ self.assertFalse(res[0]["uSNCreated"][0] == "1") # these are corrected
+ self.assertTrue("uSNChanged" in res[0])
+ self.assertFalse(res[0]["uSNChanged"][0] == "1") # these are corrected
+ self.assertTrue("whenCreated" in res[0])
+ self.assertTrue("whenChanged" in res[0])
+
+ # The objectGUID cannot directly be changed
+ try:
+ self.ldb.modify_ldif("""
+dn: cn=ldaptestcontainer,""" + self.base_dn + """
+changetype: modify
+replace: objectGUID
+objectGUID: bd3480c9-58af-4cd8-92df-bc4a18b6e44d
+""")
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+
+ self.delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
+
def test_parentGUID(self):
"""Test parentGUID behaviour"""
print "Testing parentGUID behaviour\n"
- # TODO: This seems to fail on Windows Server. Hidden attribute?
-
self.ldb.add({
"dn": "cn=parentguidtest,cn=users," + self.base_dn,
"objectclass":"user",
self.delete_force(self.ldb, "cn=testotherusers," + self.base_dn)
def test_groupType_int32(self):
- """Test groupType (int32) behaviour (should appear to be casted to a 32 bit signed integer before comparsion)"""
- print "Testing groupType (int32) behaviour\n"
-
- res1 = ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE,
- attrs=["groupType"], expression="groupType=2147483653");
-
- res2 = ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE,
- attrs=["groupType"], expression="groupType=-2147483643");
-
- self.assertEquals(len(res1), len(res2))
-
- self.assertTrue(res1.count > 0)
-
- self.assertEquals(res1[0]["groupType"][0], "-2147483643")
-
- def test_linked_attributes(self):
- """This tests the linked attribute behaviour"""
- print "Testing linked attribute behaviour\n"
-
- ldb.add({
- "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
- "objectclass": "group"})
-
- # This should not work since "memberOf" is linked to "member"
- try:
- ldb.add({
- "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
- "objectclass": ["user", "person"],
- "memberOf": "cn=ldaptestgroup,cn=users," + self.base_dn})
- except LdbError, (num, _):
- self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
-
- ldb.add({
- "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
- "objectclass": ["user", "person"]})
-
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["memberOf"] = MessageElement("cn=ldaptestgroup,cn=users," + self.base_dn,
- FLAG_MOD_ADD, "memberOf")
- try:
- ldb.modify(m)
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
-
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
- m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
- FLAG_MOD_ADD, "member")
- ldb.modify(m)
-
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["memberOf"] = MessageElement("cn=ldaptestgroup,cn=users," + self.base_dn,
- FLAG_MOD_REPLACE, "memberOf")
- try:
- ldb.modify(m)
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
-
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["memberOf"] = MessageElement("cn=ldaptestgroup,cn=users," + self.base_dn,
- FLAG_MOD_DELETE, "memberOf")
- try:
- ldb.modify(m)
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
-
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
- m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
- FLAG_MOD_DELETE, "member")
- ldb.modify(m)
-
- # This should yield no results since the member attribute for
- # "ldaptestuser" should have been deleted
- res1 = ldb.search("cn=ldaptestgroup, cn=users," + self.base_dn,
- scope=SCOPE_BASE,
- expression="(member=cn=ldaptestuser,cn=users," + self.base_dn + ")",
- attrs=[])
- self.assertTrue(len(res1) == 0)
-
- self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
-
- ldb.add({
- "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
- "objectclass": "group",
- "member": "cn=ldaptestuser,cn=users," + self.base_dn})
-
- self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
-
- # Make sure that the "member" attribute for "ldaptestuser" has been
- # removed
- res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
- scope=SCOPE_BASE, attrs=["member"])
- self.assertTrue(len(res) == 1)
- self.assertFalse("member" in res[0])
-
- self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
-
- def test_users_groups(self):
- """This tests the SAM users and groups behaviour"""
- print "Testing users and groups behaviour\n"
-
- ldb.add({
- "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
- "objectclass": "group"})
-
- ldb.add({
- "dn": "cn=ldaptestgroup2,cn=users," + self.base_dn,
- "objectclass": "group"})
-
- res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
- scope=SCOPE_BASE, attrs=["objectSID"])
- self.assertTrue(len(res1) == 1)
- group_rid_1 = security.dom_sid(ldb.schema_format_value("objectSID",
- res1[0]["objectSID"][0])).split()[1]
-
- res1 = ldb.search("cn=ldaptestgroup2,cn=users," + self.base_dn,
- scope=SCOPE_BASE, attrs=["objectSID"])
- self.assertTrue(len(res1) == 1)
- group_rid_2 = security.dom_sid(ldb.schema_format_value("objectSID",
- res1[0]["objectSID"][0])).split()[1]
-
- # Try to create a user with an invalid primary group
- try:
- ldb.add({
- "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
- "objectclass": ["user", "person"],
- "primaryGroupID": "0"})
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
- self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
-
- # Try to Create a user with a valid primary group
- try:
- ldb.add({
- "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
- "objectclass": ["user", "person"],
- "primaryGroupID": str(group_rid_1)})
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
- self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
-
- # Test to see how we should behave when the user account doesn't
- # exist
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
- "primaryGroupID")
- try:
- ldb.modify(m)
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_NO_SUCH_OBJECT)
-
- # Test to see how we should behave when the account isn't a user
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
- m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
- "primaryGroupID")
- try:
- ldb.modify(m)
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
-
- # Test default primary groups on add operations
-
- ldb.add({
- "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
- "objectclass": ["user", "person"]})
-
- res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
- scope=SCOPE_BASE, attrs=["primaryGroupID"])
- self.assertTrue(len(res1) == 1)
- self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
-
- self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
-
- ldb.add({
- "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
- "objectclass": ["user", "person"],
- "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD) })
-
- res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
- scope=SCOPE_BASE, attrs=["primaryGroupID"])
- self.assertTrue(len(res1) == 1)
- self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
-
- self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
-
- # unfortunately the INTERDOMAIN_TRUST_ACCOUNT case cannot be tested
- # since such accounts aren't directly creatable (ACCESS_DENIED)
-
- ldb.add({
- "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
- "objectclass": ["computer"],
- "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD) })
-
- res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
- scope=SCOPE_BASE, attrs=["primaryGroupID"])
- self.assertTrue(len(res1) == 1)
- self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DOMAIN_MEMBERS))
-
- self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
-
- ldb.add({
- "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
- "objectclass": ["computer"],
- "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT | UF_PASSWD_NOTREQD) })
-
- res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
- scope=SCOPE_BASE, attrs=["primaryGroupID"])
- self.assertTrue(len(res1) == 1)
- self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DCS))
-
- self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
-
- # Read-only DC accounts are only creatable by
- # UF_WORKSTATION_TRUST_ACCOUNT and work only on DCs >= 2008 (therefore
- # we have a fallback in the assertion)
- ldb.add({
- "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
- "objectclass": ["computer"],
- "userAccountControl": str(UF_PARTIAL_SECRETS_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD) })
-
- res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
- scope=SCOPE_BASE, attrs=["primaryGroupID"])
- self.assertTrue(len(res1) == 1)
- self.assertTrue(res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_READONLY_DCS) or
- res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_DOMAIN_MEMBERS))
-
- self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
-
- # Test default primary groups on modify operations
-
- ldb.add({
- "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
- "objectclass": ["user", "person"]})
-
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["userAccountControl"] = MessageElement(str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
- "userAccountControl")
- ldb.modify(m)
-
- res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
- scope=SCOPE_BASE, attrs=["primaryGroupID"])
- self.assertTrue(len(res1) == 1)
- self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
-
- # unfortunately the INTERDOMAIN_TRUST_ACCOUNT case cannot be tested
- # since such accounts aren't directly creatable (ACCESS_DENIED)
-
- self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
-
- ldb.add({
- "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
- "objectclass": ["computer"]})
-
- res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
- scope=SCOPE_BASE, attrs=["primaryGroupID"])
- self.assertTrue(len(res1) == 1)
- self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
-
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["userAccountControl"] = MessageElement(str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
- "userAccountControl")
- ldb.modify(m)
-
- res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
- scope=SCOPE_BASE, attrs=["primaryGroupID"])
- self.assertTrue(len(res1) == 1)
- self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DOMAIN_MEMBERS))
-
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["userAccountControl"] = MessageElement(str(UF_SERVER_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
- "userAccountControl")
- ldb.modify(m)
-
- res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
- scope=SCOPE_BASE, attrs=["primaryGroupID"])
- self.assertTrue(len(res1) == 1)
- self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DCS))
-
- # Read-only DC accounts are only creatable by
- # UF_WORKSTATION_TRUST_ACCOUNT and work only on DCs >= 2008 (therefore
- # we have a fallback in the assertion)
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["userAccountControl"] = MessageElement(str(UF_PARTIAL_SECRETS_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
- "userAccountControl")
- ldb.modify(m)
-
- res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
- scope=SCOPE_BASE, attrs=["primaryGroupID"])
- self.assertTrue(len(res1) == 1)
- self.assertTrue(res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_READONLY_DCS) or
- res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_DOMAIN_MEMBERS))
-
- self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
-
- # Recreate account for further tests
-
- ldb.add({
- "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
- "objectclass": ["user", "person"]})
-
- # We should be able to reset our actual primary group
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["primaryGroupID"] = MessageElement(str(DOMAIN_RID_USERS), FLAG_MOD_REPLACE,
- "primaryGroupID")
- ldb.modify(m)
-
- # Try to add invalid primary group
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
- "primaryGroupID")
- try:
- ldb.modify(m)
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
-
- # Try to make group 1 primary - should be denied since it is not yet
- # secondary
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["primaryGroupID"] = MessageElement(str(group_rid_1),
- FLAG_MOD_REPLACE, "primaryGroupID")
- try:
- ldb.modify(m)
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
-
- # Make group 1 secondary
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
- m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
- FLAG_MOD_REPLACE, "member")
- ldb.modify(m)
-
- # Make group 1 primary
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["primaryGroupID"] = MessageElement(str(group_rid_1),
- FLAG_MOD_REPLACE, "primaryGroupID")
- ldb.modify(m)
-
- # Try to delete group 1 - should be denied
- try:
- ldb.delete("cn=ldaptestgroup,cn=users," + self.base_dn)
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
-
- # Try to add group 1 also as secondary - should be denied
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
- m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
- FLAG_MOD_ADD, "member")
- try:
- ldb.modify(m)
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
-
- # Try to add invalid member to group 1 - should be denied
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
- m["member"] = MessageElement(
- "cn=ldaptestuser3,cn=users," + self.base_dn,
- FLAG_MOD_ADD, "member")
- try:
- ldb.modify(m)
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_NO_SUCH_OBJECT)
-
- # Make group 2 secondary
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
- m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
- FLAG_MOD_ADD, "member")
- ldb.modify(m)
+ """Test groupType (int32) behaviour (should appear to be casted to a 32 bit signed integer before comparsion)"""
+ print "Testing groupType (int32) behaviour\n"
- # Swap the groups
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["primaryGroupID"] = MessageElement(str(group_rid_2),
- FLAG_MOD_REPLACE, "primaryGroupID")
- ldb.modify(m)
+ res1 = ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE,
+ attrs=["groupType"], expression="groupType=2147483653");
- # Old primary group should contain a "member" attribute for the user,
- # the new shouldn't contain anymore one
- res1 = ldb.search("cn=ldaptestgroup, cn=users," + self.base_dn,
- scope=SCOPE_BASE, attrs=["member"])
- self.assertTrue(len(res1) == 1)
- self.assertTrue(len(res1[0]["member"]) == 1)
- self.assertEquals(res1[0]["member"][0].lower(),
- ("cn=ldaptestuser,cn=users," + self.base_dn).lower())
+ res2 = ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE,
+ attrs=["groupType"], expression="groupType=-2147483643");
- res1 = ldb.search("cn=ldaptestgroup2, cn=users," + self.base_dn,
- scope=SCOPE_BASE, attrs=["member"])
- self.assertTrue(len(res1) == 1)
- self.assertFalse("member" in res1[0])
+ self.assertEquals(len(res1), len(res2))
- # Also this should be denied
- try:
- ldb.add({
- "dn": "cn=ldaptestuser1,cn=users," + self.base_dn,
- "objectclass": ["user", "person"],
- "primaryGroupID": "0"})
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+ self.assertTrue(res1.count > 0)
- self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
- self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
+ self.assertEquals(res1[0]["groupType"][0], "-2147483643")
- def test_sam_attributes(self):
- """Test the behaviour of special attributes of SAM objects"""
- print "Testing the behaviour of special attributes of SAM objects\n"""
+ def test_linked_attributes(self):
+ """This tests the linked attribute behaviour"""
+ print "Testing linked attribute behaviour\n"
- ldb.add({
- "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
- "objectclass": ["user", "person"]})
ldb.add({
"dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
"objectclass": "group"})
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
- m["groupType"] = MessageElement("0", FLAG_MOD_ADD,
- "groupType")
- try:
- ldb.modify(m)
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
-
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
- m["groupType"] = MessageElement([], FLAG_MOD_DELETE,
- "groupType")
+ # This should not work since "memberOf" is linked to "member"
try:
- ldb.modify(m)
- self.fail()
+ ldb.add({
+ "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
+ "objectclass": "user",
+ "memberOf": "cn=ldaptestgroup,cn=users," + self.base_dn})
except LdbError, (num, _):
self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["primaryGroupID"] = MessageElement("0", FLAG_MOD_ADD,
- "primaryGroupID")
- try:
- ldb.modify(m)
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
+ ldb.add({
+ "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
+ "objectclass": "user"})
m = Message()
m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["primaryGroupID"] = MessageElement([], FLAG_MOD_DELETE,
- "primaryGroupID")
+ m["memberOf"] = MessageElement("cn=ldaptestgroup,cn=users," + self.base_dn,
+ FLAG_MOD_ADD, "memberOf")
try:
ldb.modify(m)
self.fail()
self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
m = Message()
- m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["userAccountControl"] = MessageElement("0", FLAG_MOD_ADD,
- "userAccountControl")
- try:
- ldb.modify(m)
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
-
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["userAccountControl"] = MessageElement([], FLAG_MOD_DELETE,
- "userAccountControl")
- try:
- ldb.modify(m)
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+ m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+ m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
+ FLAG_MOD_ADD, "member")
+ ldb.modify(m)
m = Message()
m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["sAMAccountType"] = MessageElement("0", FLAG_MOD_ADD,
- "sAMAccountType")
+ m["memberOf"] = MessageElement("cn=ldaptestgroup,cn=users," + self.base_dn,
+ FLAG_MOD_REPLACE, "memberOf")
try:
ldb.modify(m)
self.fail()
m = Message()
m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["sAMAccountType"] = MessageElement([], FLAG_MOD_REPLACE,
- "sAMAccountType")
+ m["memberOf"] = MessageElement("cn=ldaptestgroup,cn=users," + self.base_dn,
+ FLAG_MOD_DELETE, "memberOf")
try:
ldb.modify(m)
self.fail()
self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
m = Message()
- m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- m["sAMAccountType"] = MessageElement([], FLAG_MOD_DELETE,
- "sAMAccountType")
- try:
- ldb.modify(m)
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
-
- self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+ m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+ m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
+ FLAG_MOD_DELETE, "member")
+ ldb.modify(m)
- def test_primary_group_token_constructed(self):
- """Test the primary group token behaviour (hidden-generated-readonly attribute on groups) and some other constructed attributes"""
- print "Testing primary group token behaviour and other constructed attributes\n"
+ # This should yield no results since the member attribute for
+ # "ldaptestuser" should have been deleted
+ res1 = ldb.search("cn=ldaptestgroup, cn=users," + self.base_dn,
+ scope=SCOPE_BASE,
+ expression="(member=cn=ldaptestuser,cn=users," + self.base_dn + ")",
+ attrs=[])
+ self.assertTrue(len(res1) == 0)
- try:
- ldb.add({
- "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
- "objectclass": "group",
- "primaryGroupToken": "100"})
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_UNDEFINED_ATTRIBUTE_TYPE)
self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
- ldb.add({
- "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
- "objectclass": ["user", "person"]})
-
ldb.add({
"dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
- "objectclass": "group"})
-
- # Testing for one invalid, and one valid operational attribute, but also the things they are built from
- res1 = ldb.search(self.base_dn,
- scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName", "objectClass", "objectSid"])
- self.assertTrue(len(res1) == 1)
- self.assertFalse("primaryGroupToken" in res1[0])
- self.assertTrue("canonicalName" in res1[0])
- self.assertTrue("objectClass" in res1[0])
- self.assertTrue("objectSid" in res1[0])
-
- res1 = ldb.search(self.base_dn,
- scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName"])
- self.assertTrue(len(res1) == 1)
- self.assertFalse("primaryGroupToken" in res1[0])
- self.assertFalse("objectSid" in res1[0])
- self.assertFalse("objectClass" in res1[0])
- self.assertTrue("canonicalName" in res1[0])
-
- res1 = ldb.search("cn=users,"+self.base_dn,
- scope=SCOPE_BASE, attrs=["primaryGroupToken"])
- self.assertTrue(len(res1) == 1)
- self.assertFalse("primaryGroupToken" in res1[0])
-
- res1 = ldb.search("cn=ldaptestuser, cn=users," + self.base_dn,
- scope=SCOPE_BASE, attrs=["primaryGroupToken"])
- self.assertTrue(len(res1) == 1)
- self.assertFalse("primaryGroupToken" in res1[0])
-
- res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
- scope=SCOPE_BASE)
- self.assertTrue(len(res1) == 1)
- self.assertFalse("primaryGroupToken" in res1[0])
-
- res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
- scope=SCOPE_BASE, attrs=["primaryGroupToken", "objectSID"])
- self.assertTrue(len(res1) == 1)
- primary_group_token = int(res1[0]["primaryGroupToken"][0])
-
- rid = security.dom_sid(ldb.schema_format_value("objectSID", res1[0]["objectSID"][0])).split()[1]
- self.assertEquals(primary_group_token, rid)
-
- m = Message()
- m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
- m["primaryGroupToken"] = "100"
- try:
- ldb.modify(m)
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ "objectclass": "group",
+ "member": "cn=ldaptestuser,cn=users," + self.base_dn})
self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
-
- def test_tokenGroups(self):
- """Test the tokenGroups behaviour (hidden-generated-readonly attribute on SAM objects)"""
- print "Testing tokenGroups behaviour\n"
- # The domain object shouldn't contain any "tokenGroups" entry
- res = ldb.search(self.base_dn, scope=SCOPE_BASE, attrs=["tokenGroups"])
- self.assertTrue(len(res) == 1)
- self.assertFalse("tokenGroups" in res[0])
-
- # The domain administrator should contain "tokenGroups" entries
- # (the exact number depends on the domain/forest function level and the
- # DC software versions)
- res = ldb.search("cn=Administrator,cn=Users," + self.base_dn,
- scope=SCOPE_BASE, attrs=["tokenGroups"])
- self.assertTrue(len(res) == 1)
- self.assertTrue("tokenGroups" in res[0])
-
- ldb.add({
- "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
- "objectclass": ["user", "person"]})
-
- # This testuser should contain at least two "tokenGroups" entries
- # (exactly two on an unmodified "Domain Users" and "Users" group)
- res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
- scope=SCOPE_BASE, attrs=["tokenGroups"])
+ # Make sure that the "member" attribute for "ldaptestuser" has been
+ # removed
+ res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
+ scope=SCOPE_BASE, attrs=["member"])
self.assertTrue(len(res) == 1)
- self.assertTrue(len(res[0]["tokenGroups"]) >= 2)
-
- # one entry which we need to find should point to domains "Domain Users"
- # group and another entry should point to the builtin "Users"group
- domain_users_group_found = False
- users_group_found = False
- for sid in res[0]["tokenGroups"]:
- rid = security.dom_sid(ldb.schema_format_value("objectSID", sid)).split()[1]
- if rid == 513:
- domain_users_group_found = True
- if rid == 545:
- users_group_found = True
-
- self.assertTrue(domain_users_group_found)
- self.assertTrue(users_group_found)
+ self.assertFalse("member" in res[0])
- self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
+ self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
def test_wkguid(self):
"""Test Well known GUID behaviours (including DN+Binary)"""
res = self.ldb.search(base=("<WKGUID=ab1d30f3768811d1aded00c04fd8d5cd,%s>" % self.base_dn), scope=SCOPE_BASE, attrs=[])
self.assertEquals(len(res), 1)
-
+
res2 = self.ldb.search(scope=SCOPE_BASE, attrs=["wellKnownObjects"], expression=("wellKnownObjects=B:32:ab1d30f3768811d1aded00c04fd8d5cd:%s" % res[0].dn))
self.assertEquals(len(res2), 1)
self.assertEquals(len(res), 1)
self.assertTrue("subScheamSubEntry" not in res[0])
- def test_delete(self):
- """Tests the delete operation"""
- print "Tests the delete operations"""
-
- ldb.add({
- "dn": "cn=ldaptestcontainer," + self.base_dn,
- "objectclass": "container"})
- ldb.add({
- "dn": "cn=entry1,cn=ldaptestcontainer," + self.base_dn,
- "objectclass": "container"})
- ldb.add({
- "dn": "cn=entry2,cn=ldaptestcontainer," + self.base_dn,
- "objectclass": "container"})
-
- try:
- ldb.delete("cn=ldaptestcontainer," + self.base_dn)
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF)
-
- ldb.delete("cn=ldaptestcontainer," + self.base_dn, ["tree_delete:0"])
-
- try:
- res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
- scope=SCOPE_BASE, attrs=[])
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_NO_SUCH_OBJECT)
- try:
- res = ldb.search("cn=entry1,cn=ldaptestcontainer," + self.base_dn,
- scope=SCOPE_BASE, attrs=[])
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_NO_SUCH_OBJECT)
- try:
- res = ldb.search("cn=entry2,cn=ldaptestcontainer," + self.base_dn,
- scope=SCOPE_BASE, attrs=[])
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_NO_SUCH_OBJECT)
-
- self.delete_force(self.ldb, "cn=entry1,cn=ldaptestcontainer," + self.base_dn)
- self.delete_force(self.ldb, "cn=entry2,cn=ldaptestcontainer," + self.base_dn)
- self.delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
-
- # Performs some protected object delete testing
-
- res = ldb.search(base="", expression="", scope=SCOPE_BASE,
- attrs=["dsServiceName", "dNSHostName"])
- self.assertEquals(len(res), 1)
-
- try:
- ldb.delete(res[0]["dsServiceName"][0])
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
-
- res = ldb.search(self.base_dn, scope=SCOPE_SUBTREE,
- attrs=["rIDSetReferences"],
- expression="(&(objectClass=computer)(dNSHostName=" + res[0]["dNSHostName"][0] + "))")
- self.assertEquals(len(res), 1)
-
- try:
- ldb.delete(res[0]["rIDSetReferences"][0])
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
-
- try:
- ldb.delete("cn=Enterprise Schema,cn=Partitions," + self.configuration_dn)
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
-
-# TODO: This fails with LDB_ERR_NOT_ALLOWED_ON_NON_LEAF on Windows
-# try:
-# ldb.delete("cn=Enterprise Configuration,cn=Partitions," + self.configuration_dn)
-# self.fail()
-# except LdbError, (num, _):
-# self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
-
- # Performs some "systemFlags" testing
-
- # Delete failing since "SYSTEM_FLAG_DISALLOW_DELETE"
- try:
- ldb.delete("CN=Users," + self.base_dn)
- self.fail()
- except LdbError, (num, _):
- self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
-
def test_all(self):
"""Basic tests"""
ldb.add({
"dn": "cn=ldaptestuser,cn=uSers," + self.base_dn,
- "objectclass": ["user", "person"],
+ "objectclass": "user",
"cN": "LDAPtestUSER",
"givenname": "ldap",
"sn": "testy"})
self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
ldb.add({
"dn": "cn=ldaptestuser2,cn=useRs," + self.base_dn,
- "objectClass": ["person", "user"],
+ "objectClass": "user",
"cn": "LDAPtestUSER2",
"givenname": "testy",
"sn": "ldap user2"})
# ensure we cannot add it again
try:
ldb.add({"dn": "cn=ldaptestuser3,cn=userS," + self.base_dn,
- "objectClass": ["person", "user"],
+ "objectClass": "user",
"cn": "LDAPtestUSER3"})
self.fail()
except LdbError, (num, _):
# ensure can now use that name
ldb.add({"dn": "cn=ldaptestuser3,cn=users," + self.base_dn,
- "objectClass": ["person", "user"],
+ "objectClass": "user",
"cn": "LDAPtestUSER3"})
# ensure we now cannot rename
"objectClass": "container"})
ldb.add({"dn": "CN=ldaptestuser4,CN=ldaptestcontainer," + self.base_dn,
- "objectClass": ["person", "user"],
+ "objectClass": "user",
"cn": "LDAPtestUSER4"})
ldb.modify_ldif("""
user_name = "testdescriptoruser1"
user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
#
- # Test add_ldif() with SDDL security descriptor input
+ # Test an empty security descriptor (naturally this shouldn't work)
#
self.delete_force(self.ldb, user_dn)
+ try:
+ self.ldb.add({ "dn": user_dn,
+ "objectClass": "user",
+ "sAMAccountName": user_name,
+ "nTSecurityDescriptor": [] })
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ finally:
+ self.delete_force(self.ldb, user_dn)
+ #
+ # Test add_ldif() with SDDL security descriptor input
+ #
try:
sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
self.ldb.add_ldif("""
user_name = "testdescriptoruser2"
user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
#
- # Delete user object and test modify_ldif() with SDDL security descriptor input
+ # Test an empty security descriptor (naturally this shouldn't work)
+ #
+ self.delete_force(self.ldb, user_dn)
+ self.ldb.add({ "dn": user_dn,
+ "objectClass": "user",
+ "sAMAccountName": user_name })
+
+ m = Message()
+ m.dn = Dn(ldb, user_dn)
+ m["nTSecurityDescriptor"] = MessageElement([], FLAG_MOD_ADD,
+ "nTSecurityDescriptor")
+ try:
+ self.ldb.modify(m)
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+
+ m = Message()
+ m.dn = Dn(ldb, user_dn)
+ m["nTSecurityDescriptor"] = MessageElement([], FLAG_MOD_REPLACE,
+ "nTSecurityDescriptor")
+ try:
+ self.ldb.modify(m)
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+
+ m = Message()
+ m.dn = Dn(ldb, user_dn)
+ m["nTSecurityDescriptor"] = MessageElement([], FLAG_MOD_DELETE,
+ "nTSecurityDescriptor")
+ try:
+ self.ldb.modify(m)
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+
+ self.delete_force(self.ldb, user_dn)
+ #
+ # Test modify_ldif() with SDDL security descriptor input
# Add ACE to the original descriptor test
#
try:
- self.delete_force(self.ldb, user_dn)
self.ldb.add_ldif("""
dn: """ + user_dn + """
objectclass: user
finally:
self.delete_force(self.ldb, user_dn)
+ def test_dsheuristics(self):
+ """Tests the 'dSHeuristics' attribute"""
+ print "Tests the 'dSHeuristics' attribute"""
+
+ # Get the current value to restore it later
+ res = self.ldb.search("CN=Directory Service, CN=Windows NT, CN=Services, "
+ + self.configuration_dn, scope=SCOPE_BASE, attrs=["dSHeuristics"])
+ if "dSHeuristics" in res[0]:
+ dsheuristics = res[0]["dSHeuristics"][0]
+ else:
+ dsheuristics = None
+ # Should not be longer than 18 chars?
+ try:
+ self.set_dsheuristics("123ABC-+!1asdfg@#^12")
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ # If it is >= 10 chars, tenthChar should be 1
+ try:
+ self.set_dsheuristics("00020000000002")
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ # apart from the above, all char values are accepted
+ self.set_dsheuristics("123ABC-+!1asdfg@#^")
+ res = self.ldb.search("CN=Directory Service, CN=Windows NT, CN=Services, "
+ + self.configuration_dn, scope=SCOPE_BASE, attrs=["dSHeuristics"])
+ self.assertTrue("dSHeuristics" in res[0])
+ self.assertEquals(res[0]["dSHeuristics"][0], "123ABC-+!1asdfg@#^")
+ # restore old value
+ self.set_dsheuristics(dsheuristics)
+
class BaseDnTests(unittest.TestCase):
res = self.ldb.search("", scope=SCOPE_BASE,
attrs=["namingContexts", "defaultNamingContext", "schemaNamingContext", "configurationNamingContext"])
self.assertEquals(len(res), 1)
-
+
ncs = set([])
for nc in res[0]["namingContexts"]:
self.assertTrue(nc not in ncs)
self.assertTrue(res[0]["configurationNamingContext"][0] in ncs)
self.assertTrue(res[0]["schemaNamingContext"][0] in ncs)
+ def test_serverPath(self):
+ """Testing the server paths in rootDSE"""
+ res = self.ldb.search("", scope=SCOPE_BASE,
+ attrs=["dsServiceName", "serverName"])
+ self.assertEquals(len(res), 1)
+
+ self.assertTrue("CN=Servers" in res[0]["dsServiceName"][0])
+ self.assertTrue("CN=Sites" in res[0]["dsServiceName"][0])
+ self.assertTrue("CN=NTDS Settings" in res[0]["dsServiceName"][0])
+ self.assertTrue("CN=Servers" in res[0]["serverName"][0])
+ self.assertTrue("CN=Sites" in res[0]["serverName"][0])
+ self.assertFalse("CN=NTDS Settings" in res[0]["serverName"][0])
+
+ def test_dnsHostname(self):
+ """Testing the DNS hostname in rootDSE"""
+ res = self.ldb.search("", scope=SCOPE_BASE,
+ attrs=["dnsHostName", "serverName"])
+ self.assertEquals(len(res), 1)
+
+ res2 = self.ldb.search(res[0]["serverName"][0], scope=SCOPE_BASE,
+ attrs=["dNSHostName"])
+ self.assertEquals(len(res2), 1)
+
+ self.assertEquals(res[0]["dnsHostName"][0], res2[0]["dNSHostName"][0])
+
+ def test_ldapServiceName(self):
+ """Testing the ldap service name in rootDSE"""
+ res = self.ldb.search("", scope=SCOPE_BASE,
+ attrs=["ldapServiceName", "dNSHostName"])
+ self.assertEquals(len(res), 1)
+
+ (hostname, _, dns_domainname) = res[0]["dNSHostName"][0].partition(".")
+ self.assertTrue(":%s$@%s" % (hostname, dns_domainname.upper())
+ in res[0]["ldapServiceName"][0])
if not "://" in host:
if os.path.isfile(host):