s4:sam.py - test "objectSid" modification lockdown
[amitay/samba.git] / source4 / dsdb / tests / python / sam.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 # This is a port of the original in testprogs/ejs/ldap.js
4
5 import optparse
6 import sys
7 import time
8 import base64
9 import os
10
11 sys.path.append("bin/python")
12 import samba
13 samba.ensure_external_module("subunit", "subunit/python")
14 samba.ensure_external_module("testtools", "testtools")
15
16 import samba.getopt as options
17
18 from samba.auth import system_session
19 from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError
20 from ldb import ERR_NO_SUCH_OBJECT, ERR_ATTRIBUTE_OR_VALUE_EXISTS
21 from ldb import ERR_ENTRY_ALREADY_EXISTS, ERR_UNWILLING_TO_PERFORM
22 from ldb import ERR_NOT_ALLOWED_ON_NON_LEAF, ERR_OTHER, ERR_INVALID_DN_SYNTAX
23 from ldb import ERR_NO_SUCH_ATTRIBUTE
24 from ldb import ERR_OBJECT_CLASS_VIOLATION, ERR_NOT_ALLOWED_ON_RDN
25 from ldb import ERR_NAMING_VIOLATION, ERR_CONSTRAINT_VIOLATION
26 from ldb import ERR_UNDEFINED_ATTRIBUTE_TYPE, ERR_INSUFFICIENT_ACCESS_RIGHTS
27 from ldb import Message, MessageElement, Dn
28 from ldb import FLAG_MOD_ADD, FLAG_MOD_REPLACE, FLAG_MOD_DELETE
29 from samba import Ldb
30 from samba.dsdb import (UF_NORMAL_ACCOUNT, UF_INTERDOMAIN_TRUST_ACCOUNT,
31     UF_WORKSTATION_TRUST_ACCOUNT, UF_SERVER_TRUST_ACCOUNT,
32     UF_PARTIAL_SECRETS_ACCOUNT, UF_TEMP_DUPLICATE_ACCOUNT,
33     UF_PASSWD_NOTREQD, UF_ACCOUNTDISABLE, ATYPE_NORMAL_ACCOUNT,
34     GTYPE_SECURITY_BUILTIN_LOCAL_GROUP, GTYPE_SECURITY_DOMAIN_LOCAL_GROUP,
35     GTYPE_SECURITY_GLOBAL_GROUP, GTYPE_SECURITY_UNIVERSAL_GROUP,
36     GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP, GTYPE_DISTRIBUTION_GLOBAL_GROUP,
37     GTYPE_DISTRIBUTION_UNIVERSAL_GROUP,
38     ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_UNIVERSAL_GROUP,
39     ATYPE_SECURITY_LOCAL_GROUP, ATYPE_DISTRIBUTION_GLOBAL_GROUP,
40     ATYPE_DISTRIBUTION_UNIVERSAL_GROUP, ATYPE_DISTRIBUTION_LOCAL_GROUP,
41     ATYPE_WORKSTATION_TRUST, SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE,
42     SYSTEM_FLAG_CONFIG_ALLOW_RENAME, SYSTEM_FLAG_CONFIG_ALLOW_MOVE,
43     SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE)
44 from samba.dcerpc.security import (DOMAIN_RID_USERS, DOMAIN_RID_DOMAIN_MEMBERS,
45     DOMAIN_RID_DCS, DOMAIN_RID_READONLY_DCS)
46
47 from subunit.run import SubunitTestRunner
48 import unittest
49
50 from samba.ndr import ndr_pack, ndr_unpack
51 from samba.dcerpc import security
52
53 parser = optparse.OptionParser("sam.py [options] <host>")
54 sambaopts = options.SambaOptions(parser)
55 parser.add_option_group(sambaopts)
56 parser.add_option_group(options.VersionOptions(parser))
57 # use command line creds if available
58 credopts = options.CredentialsOptions(parser)
59 parser.add_option_group(credopts)
60 opts, args = parser.parse_args()
61
62 if len(args) < 1:
63     parser.print_usage()
64     sys.exit(1)
65
66 host = args[0]
67
68 lp = sambaopts.get_loadparm()
69 creds = credopts.get_credentials(lp)
70
71 class SamTests(unittest.TestCase):
72
73     def delete_force(self, ldb, dn):
74         try:
75             ldb.delete(dn)
76         except LdbError, (num, _):
77             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
78
79     def find_basedn(self, ldb):
80         res = ldb.search(base="", expression="", scope=SCOPE_BASE,
81                          attrs=["defaultNamingContext"])
82         self.assertEquals(len(res), 1)
83         return res[0]["defaultNamingContext"][0]
84
85     def find_domain_sid(self):
86         res = self.ldb.search(base=self.base_dn, expression="(objectClass=*)", scope=SCOPE_BASE)
87         return ndr_unpack( security.dom_sid,res[0]["objectSid"][0])
88
89     def setUp(self):
90         super(SamTests, self).setUp()
91         self.ldb = ldb
92         self.gc_ldb = gc_ldb
93         self.base_dn = self.find_basedn(ldb)
94         self.domain_sid = self.find_domain_sid()
95
96         print "baseDN: %s\n" % self.base_dn
97
98         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
99         self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
100         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
101         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
102         self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
103
104     def test_users_groups(self):
105         """This tests the SAM users and groups behaviour"""
106         print "Testing users and groups behaviour\n"
107
108         ldb.add({
109             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
110             "objectclass": "group"})
111
112         ldb.add({
113             "dn": "cn=ldaptestgroup2,cn=users," + self.base_dn,
114             "objectclass": "group"})
115
116         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
117                           scope=SCOPE_BASE, attrs=["objectSID"])
118         self.assertTrue(len(res1) == 1)
119         group_rid_1 = security.dom_sid(ldb.schema_format_value("objectSID",
120           res1[0]["objectSID"][0])).split()[1]
121
122         res1 = ldb.search("cn=ldaptestgroup2,cn=users," + self.base_dn,
123                           scope=SCOPE_BASE, attrs=["objectSID"])
124         self.assertTrue(len(res1) == 1)
125         group_rid_2 = security.dom_sid(ldb.schema_format_value("objectSID",
126           res1[0]["objectSID"][0])).split()[1]
127
128         # Try to create a user with an invalid account name
129         try:
130             ldb.add({
131                 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
132                 "objectclass": ["user", "person"],
133                 "sAMAccountName": "administrator"})
134             self.fail()
135         except LdbError, (num, _):
136             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
137         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
138
139         # Try to create a user with an invalid primary group
140         try:
141             ldb.add({
142                 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
143                 "objectclass": ["user", "person"],
144                 "primaryGroupID": "0"})
145             self.fail()
146         except LdbError, (num, _):
147             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
148         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
149
150         # Try to Create a user with a valid primary group
151         try:
152             ldb.add({
153                 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
154                 "objectclass": ["user", "person"],
155                 "primaryGroupID": str(group_rid_1)})
156             self.fail()
157         except LdbError, (num, _):
158             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
159         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
160
161         # Test to see how we should behave when the user account doesn't
162         # exist
163         m = Message()
164         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
165         m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
166           "primaryGroupID")
167         try:
168             ldb.modify(m)
169             self.fail()
170         except LdbError, (num, _):
171             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
172
173         # Test to see how we should behave when the account isn't a user
174         m = Message()
175         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
176         m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
177           "primaryGroupID")
178         try:
179             ldb.modify(m)
180             self.fail()
181         except LdbError, (num, _):
182             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
183
184         # Test default primary groups on add operations
185
186         ldb.add({
187             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
188             "objectclass": ["user", "person"]})
189
190         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
191                           scope=SCOPE_BASE, attrs=["primaryGroupID"])
192         self.assertTrue(len(res1) == 1)
193         self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
194
195         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
196
197         ldb.add({
198             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
199             "objectclass": ["user", "person"],
200             "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD) })
201
202         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
203                           scope=SCOPE_BASE, attrs=["primaryGroupID"])
204         self.assertTrue(len(res1) == 1)
205         self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
206
207         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
208
209         # unfortunately the INTERDOMAIN_TRUST_ACCOUNT case cannot be tested
210         # since such accounts aren't directly creatable (ACCESS_DENIED)
211
212         ldb.add({
213             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
214             "objectclass": ["computer"],
215             "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD) })
216
217         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
218                           scope=SCOPE_BASE, attrs=["primaryGroupID"])
219         self.assertTrue(len(res1) == 1)
220         self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DOMAIN_MEMBERS))
221
222         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
223
224         ldb.add({
225             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
226             "objectclass": ["computer"],
227             "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT | UF_PASSWD_NOTREQD) })
228
229         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
230                           scope=SCOPE_BASE, attrs=["primaryGroupID"])
231         self.assertTrue(len(res1) == 1)
232         self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DCS))
233
234         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
235
236         # Read-only DC accounts are only creatable by
237         # UF_WORKSTATION_TRUST_ACCOUNT and work only on DCs >= 2008 (therefore
238         # we have a fallback in the assertion)
239         ldb.add({
240             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
241             "objectclass": ["computer"],
242             "userAccountControl": str(UF_PARTIAL_SECRETS_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD) })
243
244         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
245                           scope=SCOPE_BASE, attrs=["primaryGroupID"])
246         self.assertTrue(len(res1) == 1)
247         self.assertTrue(res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_READONLY_DCS) or
248                         res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_DOMAIN_MEMBERS))
249
250         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
251
252         # Test default primary groups on modify operations
253
254         ldb.add({
255             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
256             "objectclass": ["user", "person"]})
257
258         m = Message()
259         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
260         m["userAccountControl"] = MessageElement(str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
261           "userAccountControl")
262         ldb.modify(m)
263
264         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
265                           scope=SCOPE_BASE, attrs=["primaryGroupID"])
266         self.assertTrue(len(res1) == 1)
267         self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
268
269         # unfortunately the INTERDOMAIN_TRUST_ACCOUNT case cannot be tested
270         # since such accounts aren't directly creatable (ACCESS_DENIED)
271
272         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
273
274         ldb.add({
275             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
276             "objectclass": ["computer"]})
277
278         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
279                           scope=SCOPE_BASE, attrs=["primaryGroupID"])
280         self.assertTrue(len(res1) == 1)
281         self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
282
283         m = Message()
284         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
285         m["userAccountControl"] = MessageElement(str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
286           "userAccountControl")
287         ldb.modify(m)
288
289         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
290                           scope=SCOPE_BASE, attrs=["primaryGroupID"])
291         self.assertTrue(len(res1) == 1)
292         self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DOMAIN_MEMBERS))
293
294         m = Message()
295         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
296         m["userAccountControl"] = MessageElement(str(UF_SERVER_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
297           "userAccountControl")
298         ldb.modify(m)
299
300         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
301                           scope=SCOPE_BASE, attrs=["primaryGroupID"])
302         self.assertTrue(len(res1) == 1)
303         self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DCS))
304
305         # Read-only DC accounts are only creatable by
306         # UF_WORKSTATION_TRUST_ACCOUNT and work only on DCs >= 2008 (therefore
307         # we have a fallback in the assertion)
308         m = Message()
309         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
310         m["userAccountControl"] = MessageElement(str(UF_PARTIAL_SECRETS_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
311           "userAccountControl")
312         ldb.modify(m)
313
314         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
315                           scope=SCOPE_BASE, attrs=["primaryGroupID"])
316         self.assertTrue(len(res1) == 1)
317         self.assertTrue(res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_READONLY_DCS) or
318                         res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_DOMAIN_MEMBERS))
319
320         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
321
322         # Recreate account for further tests
323
324         ldb.add({
325             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
326             "objectclass": ["user", "person"]})
327
328         # Try to set an invalid account name
329         m = Message()
330         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
331         m["sAMAccountName"] = MessageElement("administrator", FLAG_MOD_REPLACE,
332           "sAMAccountName")
333         try:
334             ldb.modify(m)
335             self.fail()
336         except LdbError, (num, _):
337             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
338
339         # But to reset the actual "sAMAccountName" should still be possible
340         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
341                           scope=SCOPE_BASE, attrs=["sAMAccountName"])
342         self.assertTrue(len(res1) == 1)
343         m = Message()
344         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
345         m["sAMAccountName"] = MessageElement(res1[0]["sAMAccountName"][0], FLAG_MOD_REPLACE,
346           "sAMAccountName")
347         ldb.modify(m)
348
349         # And another (free) name should be possible as well
350         m = Message()
351         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
352         m["sAMAccountName"] = MessageElement("xxx_ldaptestuser_xxx", FLAG_MOD_REPLACE,
353           "sAMAccountName")
354         ldb.modify(m)
355
356         # We should be able to reset our actual primary group
357         m = Message()
358         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
359         m["primaryGroupID"] = MessageElement(str(DOMAIN_RID_USERS), FLAG_MOD_REPLACE,
360           "primaryGroupID")
361         ldb.modify(m)
362
363         # Try to add invalid primary group
364         m = Message()
365         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
366         m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
367           "primaryGroupID")
368         try:
369             ldb.modify(m)
370             self.fail()
371         except LdbError, (num, _):
372             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
373
374         # Try to make group 1 primary - should be denied since it is not yet
375         # secondary
376         m = Message()
377         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
378         m["primaryGroupID"] = MessageElement(str(group_rid_1),
379           FLAG_MOD_REPLACE, "primaryGroupID")
380         try:
381             ldb.modify(m)
382             self.fail()
383         except LdbError, (num, _):
384             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
385
386         # Make group 1 secondary
387         m = Message()
388         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
389         m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
390                                      FLAG_MOD_REPLACE, "member")
391         ldb.modify(m)
392
393         # Make group 1 primary
394         m = Message()
395         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
396         m["primaryGroupID"] = MessageElement(str(group_rid_1),
397           FLAG_MOD_REPLACE, "primaryGroupID")
398         ldb.modify(m)
399
400         # Try to delete group 1 - should be denied
401         try:
402             ldb.delete("cn=ldaptestgroup,cn=users," + self.base_dn)
403             self.fail()
404         except LdbError, (num, _):
405             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
406
407         # Try to add group 1 also as secondary - should be denied
408         m = Message()
409         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
410         m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
411                                      FLAG_MOD_ADD, "member")
412         try:
413             ldb.modify(m)
414             self.fail()
415         except LdbError, (num, _):
416             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
417
418         # Try to add invalid member to group 1 - should be denied
419         m = Message()
420         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
421         m["member"] = MessageElement(
422           "cn=ldaptestuser3,cn=users," + self.base_dn,
423           FLAG_MOD_ADD, "member")
424         try:
425             ldb.modify(m)
426             self.fail()
427         except LdbError, (num, _):
428             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
429
430         # Make group 2 secondary
431         m = Message()
432         m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
433         m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
434                                      FLAG_MOD_ADD, "member")
435         ldb.modify(m)
436
437         # Swap the groups
438         m = Message()
439         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
440         m["primaryGroupID"] = MessageElement(str(group_rid_2),
441           FLAG_MOD_REPLACE, "primaryGroupID")
442         ldb.modify(m)
443
444         # Swap the groups (does not really make sense but does the same)
445         m = Message()
446         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
447         m["primaryGroupID"] = MessageElement(str(group_rid_1),
448           FLAG_MOD_REPLACE, "primaryGroupID")
449         m["primaryGroupID"] = MessageElement(str(group_rid_2),
450           FLAG_MOD_REPLACE, "primaryGroupID")
451         ldb.modify(m)
452
453         # Old primary group should contain a "member" attribute for the user,
454         # the new shouldn't contain anymore one
455         res1 = ldb.search("cn=ldaptestgroup, cn=users," + self.base_dn,
456                           scope=SCOPE_BASE, attrs=["member"])
457         self.assertTrue(len(res1) == 1)
458         self.assertTrue(len(res1[0]["member"]) == 1)
459         self.assertEquals(res1[0]["member"][0].lower(),
460           ("cn=ldaptestuser,cn=users," + self.base_dn).lower())
461
462         res1 = ldb.search("cn=ldaptestgroup2, cn=users," + self.base_dn,
463                           scope=SCOPE_BASE, attrs=["member"])
464         self.assertTrue(len(res1) == 1)
465         self.assertFalse("member" in res1[0])
466
467         # Primary group member
468         m = Message()
469         m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
470         m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
471                                      FLAG_MOD_DELETE, "member")
472         try:
473             ldb.modify(m)
474             self.fail()
475         except LdbError, (num, _):
476             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
477
478         # Delete invalid group member
479         m = Message()
480         m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
481         m["member"] = MessageElement("cn=ldaptestuser1,cn=users," + self.base_dn,
482                                      FLAG_MOD_DELETE, "member")
483         try:
484             ldb.modify(m)
485             self.fail()
486         except LdbError, (num, _):
487             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
488
489         # Also this should be denied
490         try:
491             ldb.add({
492               "dn": "cn=ldaptestuser2,cn=users," + self.base_dn,
493               "objectclass": ["user", "person"],
494               "primaryGroupID": "0"})
495             self.fail()
496         except LdbError, (num, _):
497             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
498
499         # Recreate user accounts
500
501         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
502
503         ldb.add({
504             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
505             "objectclass": ["user", "person"]})
506
507         ldb.add({
508             "dn": "cn=ldaptestuser2,cn=users," + self.base_dn,
509             "objectclass": ["user", "person"]})
510
511         m = Message()
512         m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
513         m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
514                                      FLAG_MOD_ADD, "member")
515         ldb.modify(m)
516
517         # Already added
518         m = Message()
519         m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
520         m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
521                                      FLAG_MOD_ADD, "member")
522         try:
523             ldb.modify(m)
524             self.fail()
525         except LdbError, (num, _):
526             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
527
528         # Invalid member
529         m = Message()
530         m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
531         m["member"] = MessageElement("cn=ldaptestuser1,cn=users," + self.base_dn,
532                                      FLAG_MOD_REPLACE, "member")
533         try:
534             ldb.modify(m)
535             self.fail()
536         except LdbError, (num, _):
537             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
538
539         # Invalid member
540         m = Message()
541         m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
542         m["member"] = MessageElement(["cn=ldaptestuser,cn=users," + self.base_dn,
543                                       "cn=ldaptestuser1,cn=users," + self.base_dn],
544                                      FLAG_MOD_REPLACE, "member")
545         try:
546             ldb.modify(m)
547             self.fail()
548         except LdbError, (num, _):
549             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
550
551         # Invalid member
552         m = Message()
553         m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
554         m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
555                                      FLAG_MOD_REPLACE, "member")
556         m["member"] = MessageElement("cn=ldaptestuser1,cn=users," + self.base_dn,
557                                      FLAG_MOD_ADD, "member")
558         try:
559             ldb.modify(m)
560             self.fail()
561         except LdbError, (num, _):
562             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
563
564         m = Message()
565         m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
566         m["member"] = MessageElement(["cn=ldaptestuser,cn=users," + self.base_dn,
567                                       "cn=ldaptestuser2,cn=users," + self.base_dn],
568                                      FLAG_MOD_REPLACE, "member")
569         ldb.modify(m)
570
571         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
572         self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
573         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
574         self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
575
576     def test_sam_attributes(self):
577         """Test the behaviour of special attributes of SAM objects"""
578         print "Testing the behaviour of special attributes of SAM objects\n"""
579
580         ldb.add({
581             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
582             "objectclass": ["user", "person"]})
583         ldb.add({
584             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
585             "objectclass": "group"})
586
587         m = Message()
588         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
589         m["groupType"] = MessageElement("0", FLAG_MOD_ADD,
590           "groupType")
591         try:
592             ldb.modify(m)
593             self.fail()
594         except LdbError, (num, _):
595             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
596
597         m = Message()
598         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
599         m["groupType"] = MessageElement([], FLAG_MOD_DELETE,
600           "groupType")
601         try:
602             ldb.modify(m)
603             self.fail()
604         except LdbError, (num, _):
605             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
606
607         m = Message()
608         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
609         m["primaryGroupID"] = MessageElement("0", FLAG_MOD_ADD,
610           "primaryGroupID")
611         try:
612             ldb.modify(m)
613             self.fail()
614         except LdbError, (num, _):
615             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
616
617         m = Message()
618         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
619         m["primaryGroupID"] = MessageElement([], FLAG_MOD_DELETE,
620           "primaryGroupID")
621         try:
622             ldb.modify(m)
623             self.fail()
624         except LdbError, (num, _):
625             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
626
627         m = Message()
628         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
629         m["userAccountControl"] = MessageElement("0", FLAG_MOD_ADD,
630           "userAccountControl")
631         try:
632             ldb.modify(m)
633             self.fail()
634         except LdbError, (num, _):
635             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
636
637         m = Message()
638         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
639         m["userAccountControl"] = MessageElement([], FLAG_MOD_DELETE,
640           "userAccountControl")
641         try:
642             ldb.modify(m)
643             self.fail()
644         except LdbError, (num, _):
645             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
646
647         m = Message()
648         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
649         m["objectSid"] = MessageElement("xxxxxxxxxxxxxxxx", FLAG_MOD_ADD,
650           "objectSid")
651         try:
652             ldb.modify(m)
653             self.fail()
654         except LdbError, (num, _):
655             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
656
657         m = Message()
658         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
659         m["objectSid"] = MessageElement([], FLAG_MOD_REPLACE, "objectSid")
660         try:
661             ldb.modify(m)
662             self.fail()
663         except LdbError, (num, _):
664             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
665
666         m = Message()
667         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
668         m["objectSid"] = MessageElement([], FLAG_MOD_DELETE, "objectSid")
669         try:
670             ldb.modify(m)
671             self.fail()
672         except LdbError, (num, _):
673             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
674
675         m = Message()
676         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
677         m["sAMAccountType"] = MessageElement("0", FLAG_MOD_ADD,
678           "sAMAccountType")
679         try:
680             ldb.modify(m)
681             self.fail()
682         except LdbError, (num, _):
683             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
684
685         m = Message()
686         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
687         m["sAMAccountType"] = MessageElement([], FLAG_MOD_REPLACE,
688           "sAMAccountType")
689         try:
690             ldb.modify(m)
691             self.fail()
692         except LdbError, (num, _):
693             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
694
695         m = Message()
696         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
697         m["sAMAccountType"] = MessageElement([], FLAG_MOD_DELETE,
698           "sAMAccountType")
699         try:
700             ldb.modify(m)
701             self.fail()
702         except LdbError, (num, _):
703             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
704
705         m = Message()
706         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
707         m["sAMAccountName"] = MessageElement("test", FLAG_MOD_ADD,
708           "sAMAccountName")
709         try:
710             ldb.modify(m)
711             self.fail()
712         except LdbError, (num, _):
713             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
714
715         m = Message()
716         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
717         m["sAMAccountName"] = MessageElement([], FLAG_MOD_DELETE,
718           "sAMAccountName")
719         try:
720             ldb.modify(m)
721             self.fail()
722         except LdbError, (num, _):
723             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
724
725         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
726         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
727
728     def test_primary_group_token_constructed(self):
729         """Test the primary group token behaviour (hidden-generated-readonly attribute on groups) and some other constructed attributes"""
730         print "Testing primary group token behaviour and other constructed attributes\n"
731
732         try:
733             ldb.add({
734                 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
735                 "objectclass": "group",
736                 "primaryGroupToken": "100"})
737             self.fail()
738         except LdbError, (num, _):
739             self.assertEquals(num, ERR_UNDEFINED_ATTRIBUTE_TYPE)
740         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
741
742         ldb.add({
743             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
744             "objectclass": ["user", "person"]})
745
746         ldb.add({
747             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
748             "objectclass": "group"})
749
750         # Testing for one invalid, and one valid operational attribute, but also the things they are built from
751         res1 = ldb.search(self.base_dn,
752                           scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName", "objectClass", "objectSid"])
753         self.assertTrue(len(res1) == 1)
754         self.assertFalse("primaryGroupToken" in res1[0])
755         self.assertTrue("canonicalName" in res1[0])
756         self.assertTrue("objectClass" in res1[0])
757         self.assertTrue("objectSid" in res1[0])
758
759         res1 = ldb.search(self.base_dn,
760                           scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName"])
761         self.assertTrue(len(res1) == 1)
762         self.assertFalse("primaryGroupToken" in res1[0])
763         self.assertFalse("objectSid" in res1[0])
764         self.assertFalse("objectClass" in res1[0])
765         self.assertTrue("canonicalName" in res1[0])
766
767         res1 = ldb.search("cn=users," + self.base_dn,
768                           scope=SCOPE_BASE, attrs=["primaryGroupToken"])
769         self.assertTrue(len(res1) == 1)
770         self.assertFalse("primaryGroupToken" in res1[0])
771
772         res1 = ldb.search("cn=ldaptestuser, cn=users," + self.base_dn,
773                           scope=SCOPE_BASE, attrs=["primaryGroupToken"])
774         self.assertTrue(len(res1) == 1)
775         self.assertFalse("primaryGroupToken" in res1[0])
776
777         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
778                           scope=SCOPE_BASE)
779         self.assertTrue(len(res1) == 1)
780         self.assertFalse("primaryGroupToken" in res1[0])
781
782         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
783                           scope=SCOPE_BASE, attrs=["primaryGroupToken", "objectSID"])
784         self.assertTrue(len(res1) == 1)
785         primary_group_token = int(res1[0]["primaryGroupToken"][0])
786
787         rid = security.dom_sid(ldb.schema_format_value("objectSID", res1[0]["objectSID"][0])).split()[1]
788         self.assertEquals(primary_group_token, rid)
789
790         m = Message()
791         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
792         m["primaryGroupToken"] = "100"
793         try:
794             ldb.modify(m)
795             self.fail()
796         except LdbError, (num, _):
797             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
798
799         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
800         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
801
802     def test_tokenGroups(self):
803         """Test the tokenGroups behaviour (hidden-generated-readonly attribute on SAM objects)"""
804         print "Testing tokenGroups behaviour\n"
805
806         # The domain object shouldn't contain any "tokenGroups" entry
807         res = ldb.search(self.base_dn, scope=SCOPE_BASE, attrs=["tokenGroups"])
808         self.assertTrue(len(res) == 1)
809         self.assertFalse("tokenGroups" in res[0])
810
811         # The domain administrator should contain "tokenGroups" entries
812         # (the exact number depends on the domain/forest function level and the
813         # DC software versions)
814         res = ldb.search("cn=Administrator,cn=Users," + self.base_dn,
815                          scope=SCOPE_BASE, attrs=["tokenGroups"])
816         self.assertTrue(len(res) == 1)
817         self.assertTrue("tokenGroups" in res[0])
818
819         ldb.add({
820             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
821             "objectclass": ["user", "person"]})
822
823         # This testuser should contain at least two "tokenGroups" entries
824         # (exactly two on an unmodified "Domain Users" and "Users" group)
825         res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
826                          scope=SCOPE_BASE, attrs=["tokenGroups"])
827         self.assertTrue(len(res) == 1)
828         self.assertTrue(len(res[0]["tokenGroups"]) >= 2)
829
830         # one entry which we need to find should point to domains "Domain Users"
831         # group and another entry should point to the builtin "Users"group
832         domain_users_group_found = False
833         users_group_found = False
834         for sid in res[0]["tokenGroups"]:
835             rid = security.dom_sid(ldb.schema_format_value("objectSID", sid)).split()[1]
836             if rid == 513:
837                 domain_users_group_found = True
838             if rid == 545:
839                 users_group_found = True
840
841         self.assertTrue(domain_users_group_found)
842         self.assertTrue(users_group_found)
843
844         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
845
846     def test_groupType(self):
847         """Test the groupType behaviour"""
848         print "Testing groupType behaviour\n"
849
850         # You can never create or change to a
851         # "GTYPE_SECURITY_BUILTIN_LOCAL_GROUP"
852
853         # Add operation
854
855         # Invalid attribute
856         try:
857             ldb.add({
858                 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
859                 "objectclass": "group",
860                 "groupType": "0"})
861             self.fail()
862         except LdbError, (num, _):
863             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
864         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
865
866         try:
867             ldb.add({
868                 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
869                 "objectclass": "group",
870                 "groupType": str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP)})
871             self.fail()
872         except LdbError, (num, _):
873             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
874         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
875
876         ldb.add({
877             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
878             "objectclass": "group",
879             "groupType": str(GTYPE_SECURITY_GLOBAL_GROUP)})
880
881         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
882                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
883         self.assertTrue(len(res1) == 1)
884         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
885           ATYPE_SECURITY_GLOBAL_GROUP)
886         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
887
888         ldb.add({
889             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
890             "objectclass": "group",
891             "groupType": str(GTYPE_SECURITY_UNIVERSAL_GROUP)})
892
893         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
894                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
895         self.assertTrue(len(res1) == 1)
896         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
897           ATYPE_SECURITY_UNIVERSAL_GROUP)
898         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
899
900         ldb.add({
901             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
902             "objectclass": "group",
903             "groupType": str(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP)})
904
905         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
906                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
907         self.assertTrue(len(res1) == 1)
908         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
909           ATYPE_SECURITY_LOCAL_GROUP)
910         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
911
912         ldb.add({
913             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
914             "objectclass": "group",
915             "groupType": str(GTYPE_DISTRIBUTION_GLOBAL_GROUP)})
916
917         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
918                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
919         self.assertTrue(len(res1) == 1)
920         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
921           ATYPE_DISTRIBUTION_GLOBAL_GROUP)
922         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
923
924         ldb.add({
925             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
926             "objectclass": "group",
927             "groupType": str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP)})
928
929         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
930                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
931         self.assertTrue(len(res1) == 1)
932         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
933           ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
934         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
935
936         ldb.add({
937             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
938             "objectclass": "group",
939             "groupType": str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)})
940
941         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
942                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
943         self.assertTrue(len(res1) == 1)
944         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
945           ATYPE_DISTRIBUTION_LOCAL_GROUP)
946         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
947
948         # Modify operation
949
950         ldb.add({
951             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
952             "objectclass": "group"})
953
954         # We can change in this direction: global <-> universal <-> local
955         # On each step also the group type itself (security/distribution) is
956         # variable.
957
958         # After creation we should have a "security global group"
959         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
960                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
961         self.assertTrue(len(res1) == 1)
962         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
963           ATYPE_SECURITY_GLOBAL_GROUP)
964
965         # Invalid attribute
966         try:
967             m = Message()
968             m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
969             m["groupType"] = MessageElement("0",
970               FLAG_MOD_REPLACE, "groupType")
971             ldb.modify(m)
972             self.fail()
973         except LdbError, (num, _):
974             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
975
976         # Security groups
977
978         # Default is "global group"
979
980         m = Message()
981         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
982         m["groupType"] = MessageElement(
983           str(GTYPE_SECURITY_GLOBAL_GROUP),
984           FLAG_MOD_REPLACE, "groupType")
985         ldb.modify(m)
986
987         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
988                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
989         self.assertTrue(len(res1) == 1)
990         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
991           ATYPE_SECURITY_GLOBAL_GROUP)
992
993         # Change to "local" (shouldn't work)
994
995         try:
996             m = Message()
997             m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
998             m["groupType"] = MessageElement(
999               str(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP),
1000               FLAG_MOD_REPLACE, "groupType")
1001             ldb.modify(m)
1002             self.fail()
1003         except LdbError, (num, _):
1004             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1005
1006         # Change to "universal"
1007
1008         m = Message()
1009         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1010         m["groupType"] = MessageElement(
1011          str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1012           FLAG_MOD_REPLACE, "groupType")
1013         ldb.modify(m)
1014
1015         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1016                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1017         self.assertTrue(len(res1) == 1)
1018         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1019           ATYPE_SECURITY_UNIVERSAL_GROUP)
1020
1021         # Change back to "global"
1022
1023         m = Message()
1024         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1025         m["groupType"] = MessageElement(
1026           str(GTYPE_SECURITY_GLOBAL_GROUP),
1027           FLAG_MOD_REPLACE, "groupType")
1028         ldb.modify(m)
1029
1030         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1031                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1032         self.assertTrue(len(res1) == 1)
1033         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1034           ATYPE_SECURITY_GLOBAL_GROUP)
1035
1036         # Change back to "universal"
1037
1038         m = Message()
1039         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1040         m["groupType"] = MessageElement(
1041          str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1042           FLAG_MOD_REPLACE, "groupType")
1043         ldb.modify(m)
1044
1045         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1046                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1047         self.assertTrue(len(res1) == 1)
1048         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1049           ATYPE_SECURITY_UNIVERSAL_GROUP)
1050
1051         # Change to "local"
1052
1053         m = Message()
1054         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1055         m["groupType"] = MessageElement(
1056           str(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP),
1057           FLAG_MOD_REPLACE, "groupType")
1058         ldb.modify(m)
1059
1060         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1061                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1062         self.assertTrue(len(res1) == 1)
1063         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1064           ATYPE_SECURITY_LOCAL_GROUP)
1065
1066         # Change to "global" (shouldn't work)
1067
1068         try:
1069             m = Message()
1070             m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1071             m["groupType"] = MessageElement(
1072               str(GTYPE_SECURITY_GLOBAL_GROUP),
1073               FLAG_MOD_REPLACE, "groupType")
1074             ldb.modify(m)
1075             self.fail()
1076         except LdbError, (num, _):
1077             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1078
1079         # Change to "builtin local" (shouldn't work)
1080
1081         try:
1082             m = Message()
1083             m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1084             m["groupType"] = MessageElement(
1085               str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
1086               FLAG_MOD_REPLACE, "groupType")
1087             ldb.modify(m)
1088             self.fail()
1089         except LdbError, (num, _):
1090             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1091
1092         m = Message()
1093         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1094
1095         # Change back to "universal"
1096
1097         m = Message()
1098         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1099         m["groupType"] = MessageElement(
1100          str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1101           FLAG_MOD_REPLACE, "groupType")
1102         ldb.modify(m)
1103
1104         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1105                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1106         self.assertTrue(len(res1) == 1)
1107         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1108           ATYPE_SECURITY_UNIVERSAL_GROUP)
1109
1110         # Change to "builtin local" (shouldn't work)
1111
1112         try:
1113             m = Message()
1114             m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1115             m["groupType"] = MessageElement(
1116               str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
1117               FLAG_MOD_REPLACE, "groupType")
1118             ldb.modify(m)
1119             self.fail()
1120         except LdbError, (num, _):
1121             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1122
1123         # Change back to "global"
1124
1125         m = Message()
1126         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1127         m["groupType"] = MessageElement(
1128           str(GTYPE_SECURITY_GLOBAL_GROUP),
1129           FLAG_MOD_REPLACE, "groupType")
1130         ldb.modify(m)
1131
1132         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1133                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1134         self.assertTrue(len(res1) == 1)
1135         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1136           ATYPE_SECURITY_GLOBAL_GROUP)
1137
1138         # Change to "builtin local" (shouldn't work)
1139
1140         try:
1141             m = Message()
1142             m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1143             m["groupType"] = MessageElement(
1144               str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
1145               FLAG_MOD_REPLACE, "groupType")
1146             ldb.modify(m)
1147             self.fail()
1148         except LdbError, (num, _):
1149             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1150
1151         # Distribution groups
1152
1153         # Default is "global group"
1154
1155         m = Message()
1156         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1157         m["groupType"] = MessageElement(
1158           str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1159           FLAG_MOD_REPLACE, "groupType")
1160         ldb.modify(m)
1161
1162         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1163                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1164         self.assertTrue(len(res1) == 1)
1165         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1166           ATYPE_DISTRIBUTION_GLOBAL_GROUP)
1167
1168         # Change to local (shouldn't work)
1169
1170         try:
1171             m = Message()
1172             m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1173             m["groupType"] = MessageElement(
1174               str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1175               FLAG_MOD_REPLACE, "groupType")
1176             ldb.modify(m)
1177             self.fail()
1178         except LdbError, (num, _):
1179             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1180
1181         # Change to "universal"
1182
1183         m = Message()
1184         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1185         m["groupType"] = MessageElement(
1186          str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1187           FLAG_MOD_REPLACE, "groupType")
1188         ldb.modify(m)
1189
1190         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1191                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1192         self.assertTrue(len(res1) == 1)
1193         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1194           ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1195
1196         # Change back to "global"
1197
1198         m = Message()
1199         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1200         m["groupType"] = MessageElement(
1201           str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1202           FLAG_MOD_REPLACE, "groupType")
1203         ldb.modify(m)
1204
1205         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1206                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1207         self.assertTrue(len(res1) == 1)
1208         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1209           ATYPE_DISTRIBUTION_GLOBAL_GROUP)
1210
1211         # Change back to "universal"
1212
1213         m = Message()
1214         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1215         m["groupType"] = MessageElement(
1216          str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1217           FLAG_MOD_REPLACE, "groupType")
1218         ldb.modify(m)
1219
1220         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1221                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1222         self.assertTrue(len(res1) == 1)
1223         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1224           ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1225
1226         # Change to "local"
1227
1228         m = Message()
1229         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1230         m["groupType"] = MessageElement(
1231           str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1232           FLAG_MOD_REPLACE, "groupType")
1233         ldb.modify(m)
1234
1235         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1236                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1237         self.assertTrue(len(res1) == 1)
1238         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1239           ATYPE_DISTRIBUTION_LOCAL_GROUP)
1240
1241         # Change to "global" (shouldn't work)
1242
1243         try:
1244             m = Message()
1245             m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1246             m["groupType"] = MessageElement(
1247               str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1248               FLAG_MOD_REPLACE, "groupType")
1249             ldb.modify(m)
1250             self.fail()
1251         except LdbError, (num, _):
1252             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1253
1254         # Change back to "universal"
1255
1256         # Try to add invalid member to group 1 - should be denied
1257         m = Message()
1258         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1259         m["member"] = MessageElement(
1260           "cn=ldaptestuser3,cn=users," + self.base_dn,
1261           FLAG_MOD_ADD, "member")
1262         try:
1263             ldb.modify(m)
1264             self.fail()
1265         except LdbError, (num, _):
1266             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1267
1268         # Make group 2 secondary
1269         m = Message()
1270         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1271         m["groupType"] = MessageElement(
1272          str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1273           FLAG_MOD_REPLACE, "groupType")
1274         ldb.modify(m)
1275
1276         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1277                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1278         self.assertTrue(len(res1) == 1)
1279         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1280           ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1281
1282         # Change back to "global"
1283
1284         m = Message()
1285         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1286         m["groupType"] = MessageElement(
1287           str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1288           FLAG_MOD_REPLACE, "groupType")
1289         ldb.modify(m)
1290
1291         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1292                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1293         self.assertTrue(len(res1) == 1)
1294         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1295           ATYPE_DISTRIBUTION_GLOBAL_GROUP)
1296
1297         # Both group types: this performs only random checks - all possibilities
1298         # would require too much code.
1299
1300         # Default is "global group"
1301
1302         m = Message()
1303         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1304         m["groupType"] = MessageElement(
1305           str(GTYPE_SECURITY_GLOBAL_GROUP),
1306           FLAG_MOD_REPLACE, "groupType")
1307         ldb.modify(m)
1308
1309         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1310                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1311         self.assertTrue(len(res1) == 1)
1312         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1313           ATYPE_SECURITY_GLOBAL_GROUP)
1314
1315         # Change to "local" (shouldn't work)
1316
1317         try:
1318             m = Message()
1319             m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1320             m["groupType"] = MessageElement(
1321               str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1322               FLAG_MOD_REPLACE, "groupType")
1323             ldb.modify(m)
1324             self.fail()
1325         except LdbError, (num, _):
1326             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1327
1328         # Change to "universal"
1329
1330         m = Message()
1331         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1332         m["groupType"] = MessageElement(
1333          str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1334           FLAG_MOD_REPLACE, "groupType")
1335         ldb.modify(m)
1336
1337         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1338                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1339         self.assertTrue(len(res1) == 1)
1340         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1341           ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1342
1343         # Change back to "global"
1344
1345         m = Message()
1346         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1347         m["groupType"] = MessageElement(
1348           str(GTYPE_SECURITY_GLOBAL_GROUP),
1349           FLAG_MOD_REPLACE, "groupType")
1350         ldb.modify(m)
1351
1352         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1353                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1354         self.assertTrue(len(res1) == 1)
1355         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1356           ATYPE_SECURITY_GLOBAL_GROUP)
1357
1358         # Change back to "universal"
1359
1360         m = Message()
1361         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1362         m["groupType"] = MessageElement(
1363          str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1364           FLAG_MOD_REPLACE, "groupType")
1365         ldb.modify(m)
1366
1367         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1368                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1369         self.assertTrue(len(res1) == 1)
1370         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1371           ATYPE_SECURITY_UNIVERSAL_GROUP)
1372
1373         # Change to "local"
1374
1375         m = Message()
1376         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1377         m["groupType"] = MessageElement(
1378           str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1379           FLAG_MOD_REPLACE, "groupType")
1380         ldb.modify(m)
1381
1382         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1383                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1384         self.assertTrue(len(res1) == 1)
1385         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1386           ATYPE_DISTRIBUTION_LOCAL_GROUP)
1387
1388         # Change to "global" (shouldn't work)
1389
1390         try:
1391             m = Message()
1392             m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1393             m["groupType"] = MessageElement(
1394               str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1395               FLAG_MOD_REPLACE, "groupType")
1396             ldb.modify(m)
1397             self.fail()
1398         except LdbError, (num, _):
1399             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1400
1401         # Change back to "universal"
1402
1403         m = Message()
1404         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1405         m["groupType"] = MessageElement(
1406          str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1407           FLAG_MOD_REPLACE, "groupType")
1408         ldb.modify(m)
1409
1410         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1411                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1412         self.assertTrue(len(res1) == 1)
1413         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1414           ATYPE_SECURITY_UNIVERSAL_GROUP)
1415
1416         # Change back to "global"
1417
1418         m = Message()
1419         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1420         m["groupType"] = MessageElement(
1421           str(GTYPE_SECURITY_GLOBAL_GROUP),
1422           FLAG_MOD_REPLACE, "groupType")
1423         ldb.modify(m)
1424
1425         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1426                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1427         self.assertTrue(len(res1) == 1)
1428         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1429           ATYPE_SECURITY_GLOBAL_GROUP)
1430
1431         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1432
1433     def test_userAccountControl(self):
1434         """Test the userAccountControl behaviour"""
1435         print "Testing userAccountControl behaviour\n"
1436
1437         # With a user object
1438
1439         # Add operation
1440
1441         # As user you can only set a normal account.
1442         # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
1443         # password yet.
1444         # With SYSTEM rights you can set a interdomain trust account.
1445
1446         # Invalid attribute
1447         try:
1448             ldb.add({
1449                 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1450                 "objectclass": ["user", "person"],
1451                 "userAccountControl": "0"})
1452             self.fail()
1453         except LdbError, (num, _):
1454             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1455         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1456
1457 # This has to wait until s4 supports it (needs a password module change)
1458 #        try:
1459 #            ldb.add({
1460 #                "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1461 #                "objectclass": ["user", "person"],
1462 #                "userAccountControl": str(UF_NORMAL_ACCOUNT)})
1463 #            self.fail()
1464 #        except LdbError, (num, _):
1465 #            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1466 #        self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1467
1468         ldb.add({
1469             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1470             "objectclass": ["user", "person"],
1471             "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD)})
1472
1473         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1474                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1475         self.assertTrue(len(res1) == 1)
1476         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1477           ATYPE_NORMAL_ACCOUNT)
1478         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1479
1480         try:
1481             ldb.add({
1482                 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1483                 "objectclass": ["user", "person"],
1484                 "userAccountControl": str(UF_TEMP_DUPLICATE_ACCOUNT)})
1485             self.fail()
1486         except LdbError, (num, _):
1487             self.assertEquals(num, ERR_OTHER)
1488         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1489
1490 # This isn't supported yet in s4
1491 #        try:
1492 #            ldb.add({
1493 #                "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1494 #                "objectclass": ["user", "person"],
1495 #                "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT)})
1496 #            self.fail()
1497 #        except LdbError, (num, _):
1498 #            self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
1499 #        self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1500 #
1501 #        try:
1502 #            ldb.add({
1503 #                "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1504 #                "objectclass": ["user", "person"],
1505 #                "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT)})
1506 #        except LdbError, (num, _):
1507 #            self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
1508 #        self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1509
1510 # This isn't supported yet in s4 - needs ACL module adaption
1511 #        try:
1512 #            ldb.add({
1513 #                "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1514 #                "objectclass": ["user", "person"],
1515 #                "userAccountControl": str(UF_INTERDOMAIN_TRUST_ACCOUNT)})
1516 #            self.fail()
1517 #        except LdbError, (num, _):
1518 #            self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1519 #        self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1520
1521         # Modify operation
1522
1523         ldb.add({
1524             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1525             "objectclass": ["user", "person"]})
1526
1527         # After creation we should have a normal account
1528         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1529                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1530         self.assertTrue(len(res1) == 1)
1531         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1532           ATYPE_NORMAL_ACCOUNT)
1533
1534         # As user you can only switch from a normal account to a workstation
1535         # trust account and back.
1536         # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
1537         # password yet.
1538         # With SYSTEM rights you can switch to a interdomain trust account.
1539
1540         # Invalid attribute
1541         try:
1542             m = Message()
1543             m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1544             m["userAccountControl"] = MessageElement("0",
1545               FLAG_MOD_REPLACE, "userAccountControl")
1546             ldb.modify(m)
1547         except LdbError, (num, _):
1548             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1549
1550 # This has to wait until s4 supports it (needs a password module change)
1551 #        try:
1552 #            m = Message()
1553 #            m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1554 #            m["userAccountControl"] = MessageElement(
1555 #              str(UF_NORMAL_ACCOUNT),
1556 #              FLAG_MOD_REPLACE, "userAccountControl")
1557 #            ldb.modify(m)
1558 #        except LdbError, (num, _):
1559 #            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1560
1561         m = Message()
1562         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1563         m["userAccountControl"] = MessageElement(
1564           str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
1565           FLAG_MOD_REPLACE, "userAccountControl")
1566         ldb.modify(m)
1567
1568         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1569                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1570         self.assertTrue(len(res1) == 1)
1571         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1572           ATYPE_NORMAL_ACCOUNT)
1573
1574         try:
1575             m = Message()
1576             m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1577             m["userAccountControl"] = MessageElement(
1578               str(UF_TEMP_DUPLICATE_ACCOUNT),
1579               FLAG_MOD_REPLACE, "userAccountControl")
1580             ldb.modify(m)
1581             self.fail()
1582         except LdbError, (num, _):
1583             self.assertEquals(num, ERR_OTHER)
1584
1585 # This isn't supported yet in s4
1586 #        try:
1587 #            m = Message()
1588 #            m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1589 #            m["userAccountControl"] = MessageElement(
1590 #              str(UF_SERVER_TRUST_ACCOUNT),
1591 #              FLAG_MOD_REPLACE, "userAccountControl")
1592 #            ldb.modify(m)
1593 #            self.fail()
1594 #        except LdbError, (num, _):
1595 #            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1596
1597         m = Message()
1598         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1599         m["userAccountControl"] = MessageElement(
1600           str(UF_WORKSTATION_TRUST_ACCOUNT),
1601           FLAG_MOD_REPLACE, "userAccountControl")
1602         ldb.modify(m)
1603
1604         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1605                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1606         self.assertTrue(len(res1) == 1)
1607         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1608           ATYPE_WORKSTATION_TRUST)
1609
1610         m = Message()
1611         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1612         m["userAccountControl"] = MessageElement(
1613           str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
1614           FLAG_MOD_REPLACE, "userAccountControl")
1615         ldb.modify(m)
1616
1617         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1618                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1619         self.assertTrue(len(res1) == 1)
1620         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1621           ATYPE_NORMAL_ACCOUNT)
1622
1623 # This isn't supported yet in s4 - needs ACL module adaption
1624 #        try:
1625 #            m = Message()
1626 #            m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1627 #            m["userAccountControl"] = MessageElement(
1628 #              str(UF_INTERDOMAIN_TRUST_ACCOUNT),
1629 #              FLAG_MOD_REPLACE, "userAccountControl")
1630 #            ldb.modify(m)
1631 #            self.fail()
1632 #        except LdbError, (num, _):
1633 #            self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1634
1635         # With a computer object
1636
1637         # Add operation
1638
1639         # As computer you can set a normal account and a server trust account.
1640         # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
1641         # password yet.
1642         # With SYSTEM rights you can set a interdomain trust account.
1643
1644         # Invalid attribute
1645         try:
1646             ldb.add({
1647                 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1648                 "objectclass": ["computer"],
1649                 "userAccountControl": "0"})
1650             self.fail()
1651         except LdbError, (num, _):
1652             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1653         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1654
1655 # This has to wait until s4 supports it (needs a password module change)
1656 #        try:
1657 #            ldb.add({
1658 #                "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1659 #                "objectclass": ["computer"],
1660 #                "userAccountControl": str(UF_NORMAL_ACCOUNT)})
1661 #            self.fail()
1662 #        except LdbError, (num, _):
1663 #            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1664 #        self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1665
1666         ldb.add({
1667             "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1668             "objectclass": ["computer"],
1669             "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD)})
1670
1671         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1672                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1673         self.assertTrue(len(res1) == 1)
1674         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1675           ATYPE_NORMAL_ACCOUNT)
1676         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1677
1678         try:
1679             ldb.add({
1680                 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1681                 "objectclass": ["computer"],
1682                 "userAccountControl": str(UF_TEMP_DUPLICATE_ACCOUNT)})
1683             self.fail()
1684         except LdbError, (num, _):
1685             self.assertEquals(num, ERR_OTHER)
1686         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1687
1688         ldb.add({
1689             "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1690             "objectclass": ["computer"],
1691             "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT)})
1692
1693         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1694                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1695         self.assertTrue(len(res1) == 1)
1696         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1697           ATYPE_WORKSTATION_TRUST)
1698         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1699
1700         try:
1701             ldb.add({
1702                 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1703                 "objectclass": ["computer"],
1704                 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT)})
1705         except LdbError, (num, _):
1706             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
1707         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1708
1709 # This isn't supported yet in s4 - needs ACL module adaption
1710 #        try:
1711 #            ldb.add({
1712 #                "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1713 #                "objectclass": ["computer"],
1714 #                "userAccountControl": str(UF_INTERDOMAIN_TRUST_ACCOUNT)})
1715 #            self.fail()
1716 #        except LdbError, (num, _):
1717 #            self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1718 #        self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1719
1720         # Modify operation
1721
1722         ldb.add({
1723             "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1724             "objectclass": ["computer"]})
1725
1726         # After creation we should have a normal account
1727         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1728                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1729         self.assertTrue(len(res1) == 1)
1730         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1731           ATYPE_NORMAL_ACCOUNT)
1732
1733         # As computer you can switch from a normal account to a workstation
1734         # or server trust account and back (also swapping between trust
1735         # accounts is allowed).
1736         # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
1737         # password yet.
1738         # With SYSTEM rights you can switch to a interdomain trust account.
1739
1740         # Invalid attribute
1741         try:
1742             m = Message()
1743             m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1744             m["userAccountControl"] = MessageElement("0",
1745               FLAG_MOD_REPLACE, "userAccountControl")
1746             ldb.modify(m)
1747         except LdbError, (num, _):
1748             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1749
1750 # This has to wait until s4 supports it (needs a password module change)
1751 #        try:
1752 #            m = Message()
1753 #            m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1754 #            m["userAccountControl"] = MessageElement(
1755 #              str(UF_NORMAL_ACCOUNT),
1756 #              FLAG_MOD_REPLACE, "userAccountControl")
1757 #            ldb.modify(m)
1758 #        except LdbError, (num, _):
1759 #            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1760
1761         m = Message()
1762         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1763         m["userAccountControl"] = MessageElement(
1764           str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
1765           FLAG_MOD_REPLACE, "userAccountControl")
1766         ldb.modify(m)
1767
1768         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1769                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1770         self.assertTrue(len(res1) == 1)
1771         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1772           ATYPE_NORMAL_ACCOUNT)
1773
1774         try:
1775             m = Message()
1776             m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1777             m["userAccountControl"] = MessageElement(
1778               str(UF_TEMP_DUPLICATE_ACCOUNT),
1779               FLAG_MOD_REPLACE, "userAccountControl")
1780             ldb.modify(m)
1781             self.fail()
1782         except LdbError, (num, _):
1783             self.assertEquals(num, ERR_OTHER)
1784
1785         m = Message()
1786         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1787         m["userAccountControl"] = MessageElement(
1788           str(UF_SERVER_TRUST_ACCOUNT),
1789           FLAG_MOD_REPLACE, "userAccountControl")
1790         ldb.modify(m)
1791
1792         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1793                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1794         self.assertTrue(len(res1) == 1)
1795         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1796           ATYPE_WORKSTATION_TRUST)
1797
1798         m = Message()
1799         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1800         m["userAccountControl"] = MessageElement(
1801           str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
1802           FLAG_MOD_REPLACE, "userAccountControl")
1803         ldb.modify(m)
1804
1805         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1806                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1807         self.assertTrue(len(res1) == 1)
1808         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1809           ATYPE_NORMAL_ACCOUNT)
1810
1811         m = Message()
1812         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1813         m["userAccountControl"] = MessageElement(
1814           str(UF_WORKSTATION_TRUST_ACCOUNT),
1815           FLAG_MOD_REPLACE, "userAccountControl")
1816         ldb.modify(m)
1817
1818         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1819                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1820         self.assertTrue(len(res1) == 1)
1821         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1822           ATYPE_WORKSTATION_TRUST)
1823
1824         m = Message()
1825         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1826         m["userAccountControl"] = MessageElement(
1827           str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
1828           FLAG_MOD_REPLACE, "userAccountControl")
1829         ldb.modify(m)
1830
1831         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1832                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1833         self.assertTrue(len(res1) == 1)
1834         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1835           ATYPE_NORMAL_ACCOUNT)
1836
1837         m = Message()
1838         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1839         m["userAccountControl"] = MessageElement(
1840           str(UF_SERVER_TRUST_ACCOUNT),
1841           FLAG_MOD_REPLACE, "userAccountControl")
1842         ldb.modify(m)
1843
1844         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1845                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1846         self.assertTrue(len(res1) == 1)
1847         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1848           ATYPE_WORKSTATION_TRUST)
1849
1850         m = Message()
1851         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1852         m["userAccountControl"] = MessageElement(
1853           str(UF_WORKSTATION_TRUST_ACCOUNT),
1854           FLAG_MOD_REPLACE, "userAccountControl")
1855         ldb.modify(m)
1856
1857         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1858                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1859         self.assertTrue(len(res1) == 1)
1860         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1861           ATYPE_WORKSTATION_TRUST)
1862
1863 # This isn't supported yet in s4 - needs ACL module adaption
1864 #        try:
1865 #            m = Message()
1866 #            m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1867 #            m["userAccountControl"] = MessageElement(
1868 #              str(UF_INTERDOMAIN_TRUST_ACCOUNT),
1869 #              FLAG_MOD_REPLACE, "userAccountControl")
1870 #            ldb.modify(m)
1871 #            self.fail()
1872 #        except LdbError, (num, _):
1873 #            self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1874
1875         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1876         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1877
1878     def test_dNSHostName(self):
1879         """Test the dNSHostName behaviour"""
1880         print "Testing dNSHostName behaviour\n"
1881
1882         ldb.add({
1883             "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1884             "objectclass": "computer",
1885             "dNSHostName": "testname.testdom"})
1886
1887         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1888                           scope=SCOPE_BASE, attrs=["servicePrincipalName"])
1889         self.assertTrue(len(res) == 1)
1890         self.assertFalse("servicePrincipalName" in res[0])
1891
1892         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1893
1894         ldb.add({
1895             "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1896             "objectclass": "computer",
1897             "servicePrincipalName": "HOST/testname.testdom"})
1898
1899         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1900                           scope=SCOPE_BASE, attrs=["dNSHostName"])
1901         self.assertTrue(len(res) == 1)
1902         self.assertFalse("dNSHostName" in res[0])
1903
1904         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1905
1906         ldb.add({
1907             "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1908             "objectclass": "computer",
1909             "dNSHostName": "testname2.testdom",
1910             "servicePrincipalName": "HOST/testname.testdom"})
1911
1912         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1913                           scope=SCOPE_BASE, attrs=["dNSHostName"])
1914         self.assertTrue(len(res) == 1)
1915         self.assertEquals(res[0]["dNSHostName"][0], "testname2.testdom")
1916
1917         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1918                           scope=SCOPE_BASE, attrs=["servicePrincipalName"])
1919         self.assertTrue(len(res) == 1)
1920         self.assertEquals(res[0]["servicePrincipalName"][0],
1921                           "HOST/testname.testdom")
1922
1923         m = Message()
1924         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1925         m["dNSHostName"] = MessageElement("testname.testdoM",
1926                                           FLAG_MOD_REPLACE, "dNSHostName")
1927         ldb.modify(m)
1928
1929         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1930                           scope=SCOPE_BASE, attrs=["servicePrincipalName"])
1931         self.assertTrue(len(res) == 1)
1932         self.assertEquals(res[0]["servicePrincipalName"][0],
1933                           "HOST/testname.testdom")
1934
1935         m = Message()
1936         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1937         m["dNSHostName"] = MessageElement("testname2.testdom2",
1938                                           FLAG_MOD_REPLACE, "dNSHostName")
1939         ldb.modify(m)
1940
1941         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1942                           scope=SCOPE_BASE, attrs=["servicePrincipalName"])
1943         self.assertTrue(len(res) == 1)
1944         self.assertEquals(res[0]["servicePrincipalName"][0],
1945                           "HOST/testname2.testdom2")
1946
1947         m = Message()
1948         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1949         m["dNSHostName"] = MessageElement([],
1950                                           FLAG_MOD_DELETE, "dNSHostName")
1951         ldb.modify(m)
1952
1953         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1954                           scope=SCOPE_BASE, attrs=["servicePrincipalName"])
1955         self.assertTrue(len(res) == 1)
1956         self.assertEquals(res[0]["servicePrincipalName"][0],
1957                           "HOST/testname2.testdom2")
1958
1959         m = Message()
1960         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1961         m["dNSHostName"] = MessageElement("testname.testdom3",
1962                                           FLAG_MOD_REPLACE, "dNSHostName")
1963         ldb.modify(m)
1964
1965         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1966                           scope=SCOPE_BASE, attrs=["servicePrincipalName"])
1967         self.assertTrue(len(res) == 1)
1968         self.assertEquals(res[0]["servicePrincipalName"][0],
1969                           "HOST/testname2.testdom2")
1970
1971         m = Message()
1972         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1973         m["dNSHostName"] = MessageElement("testname2.testdom2",
1974                                           FLAG_MOD_REPLACE, "dNSHostName")
1975         ldb.modify(m)
1976
1977         m = Message()
1978         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1979         m["dNSHostName"] = MessageElement("testname3.testdom3",
1980                                           FLAG_MOD_REPLACE, "dNSHostName")
1981         m["servicePrincipalName"] = MessageElement("HOST/testname2.testdom2",
1982                                                    FLAG_MOD_REPLACE,
1983                                                    "servicePrincipalName")
1984         ldb.modify(m)
1985
1986         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1987                           scope=SCOPE_BASE, attrs=["servicePrincipalName"])
1988         self.assertTrue(len(res) == 1)
1989         self.assertEquals(res[0]["servicePrincipalName"][0],
1990                           "HOST/testname3.testdom3")
1991
1992         m = Message()
1993         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1994         m["servicePrincipalName"] = MessageElement("HOST/testname2.testdom2",
1995                                                    FLAG_MOD_REPLACE,
1996                                                    "servicePrincipalName")
1997         m["dNSHostName"] = MessageElement("testname4.testdom4",
1998                                           FLAG_MOD_REPLACE, "dNSHostName")
1999         ldb.modify(m)
2000
2001         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2002                           scope=SCOPE_BASE, attrs=["servicePrincipalName"])
2003         self.assertTrue(len(res) == 1)
2004         self.assertEquals(res[0]["servicePrincipalName"][0],
2005                           "HOST/testname2.testdom2")
2006
2007         m = Message()
2008         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2009         m["servicePrincipalName"] = MessageElement([],
2010                                                    FLAG_MOD_DELETE,
2011                                                    "servicePrincipalName")
2012         ldb.modify(m)
2013
2014         m = Message()
2015         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2016         m["dNSHostName"] = MessageElement("testname2.testdom2",
2017                                           FLAG_MOD_REPLACE, "dNSHostName")
2018         ldb.modify(m)
2019
2020         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2021                           scope=SCOPE_BASE, attrs=["servicePrincipalName"])
2022         self.assertTrue(len(res) == 1)
2023         self.assertFalse("servicePrincipalName" in res[0])
2024
2025         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2026
2027
2028 if not "://" in host:
2029     if os.path.isfile(host):
2030         host = "tdb://%s" % host
2031     else:
2032         host = "ldap://%s" % host
2033
2034 ldb = Ldb(host, credentials=creds, session_info=system_session(), lp=lp)
2035 if not "tdb://" in host:
2036     gc_ldb = Ldb("%s:3268" % host, credentials=creds,
2037                  session_info=system_session(), lp=lp)
2038 else:
2039     gc_ldb = None
2040
2041 runner = SubunitTestRunner()
2042 rc = 0
2043 if not runner.run(unittest.makeSuite(SamTests)).wasSuccessful():
2044     rc = 1
2045 sys.exit(rc)