s4:sam.py - test the "sAMAccountName" attribute
[obnox/samba/samba-obnox.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["sAMAccountType"] = MessageElement("0", FLAG_MOD_ADD,
650           "sAMAccountType")
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["sAMAccountType"] = MessageElement([], FLAG_MOD_REPLACE,
660           "sAMAccountType")
661         try:
662             ldb.modify(m)
663             self.fail()
664         except LdbError, (num, _):
665             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
666
667         m = Message()
668         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
669         m["sAMAccountType"] = MessageElement([], FLAG_MOD_DELETE,
670           "sAMAccountType")
671         try:
672             ldb.modify(m)
673             self.fail()
674         except LdbError, (num, _):
675             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
676
677         m = Message()
678         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
679         m["sAMAccountName"] = MessageElement("test", FLAG_MOD_ADD,
680           "sAMAccountName")
681         try:
682             ldb.modify(m)
683             self.fail()
684         except LdbError, (num, _):
685             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
686
687         m = Message()
688         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
689         m["sAMAccountName"] = MessageElement([], FLAG_MOD_DELETE,
690           "sAMAccountName")
691         try:
692             ldb.modify(m)
693             self.fail()
694         except LdbError, (num, _):
695             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
696
697         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
698         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
699
700     def test_primary_group_token_constructed(self):
701         """Test the primary group token behaviour (hidden-generated-readonly attribute on groups) and some other constructed attributes"""
702         print "Testing primary group token behaviour and other constructed attributes\n"
703
704         try:
705             ldb.add({
706                 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
707                 "objectclass": "group",
708                 "primaryGroupToken": "100"})
709             self.fail()
710         except LdbError, (num, _):
711             self.assertEquals(num, ERR_UNDEFINED_ATTRIBUTE_TYPE)
712         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
713
714         ldb.add({
715             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
716             "objectclass": ["user", "person"]})
717
718         ldb.add({
719             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
720             "objectclass": "group"})
721
722         # Testing for one invalid, and one valid operational attribute, but also the things they are built from
723         res1 = ldb.search(self.base_dn,
724                           scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName", "objectClass", "objectSid"])
725         self.assertTrue(len(res1) == 1)
726         self.assertFalse("primaryGroupToken" in res1[0])
727         self.assertTrue("canonicalName" in res1[0])
728         self.assertTrue("objectClass" in res1[0])
729         self.assertTrue("objectSid" in res1[0])
730
731         res1 = ldb.search(self.base_dn,
732                           scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName"])
733         self.assertTrue(len(res1) == 1)
734         self.assertFalse("primaryGroupToken" in res1[0])
735         self.assertFalse("objectSid" in res1[0])
736         self.assertFalse("objectClass" in res1[0])
737         self.assertTrue("canonicalName" in res1[0])
738
739         res1 = ldb.search("cn=users," + self.base_dn,
740                           scope=SCOPE_BASE, attrs=["primaryGroupToken"])
741         self.assertTrue(len(res1) == 1)
742         self.assertFalse("primaryGroupToken" in res1[0])
743
744         res1 = ldb.search("cn=ldaptestuser, cn=users," + self.base_dn,
745                           scope=SCOPE_BASE, attrs=["primaryGroupToken"])
746         self.assertTrue(len(res1) == 1)
747         self.assertFalse("primaryGroupToken" in res1[0])
748
749         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
750                           scope=SCOPE_BASE)
751         self.assertTrue(len(res1) == 1)
752         self.assertFalse("primaryGroupToken" in res1[0])
753
754         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
755                           scope=SCOPE_BASE, attrs=["primaryGroupToken", "objectSID"])
756         self.assertTrue(len(res1) == 1)
757         primary_group_token = int(res1[0]["primaryGroupToken"][0])
758
759         rid = security.dom_sid(ldb.schema_format_value("objectSID", res1[0]["objectSID"][0])).split()[1]
760         self.assertEquals(primary_group_token, rid)
761
762         m = Message()
763         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
764         m["primaryGroupToken"] = "100"
765         try:
766             ldb.modify(m)
767             self.fail()
768         except LdbError, (num, _):
769             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
770
771         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
772         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
773
774     def test_tokenGroups(self):
775         """Test the tokenGroups behaviour (hidden-generated-readonly attribute on SAM objects)"""
776         print "Testing tokenGroups behaviour\n"
777
778         # The domain object shouldn't contain any "tokenGroups" entry
779         res = ldb.search(self.base_dn, scope=SCOPE_BASE, attrs=["tokenGroups"])
780         self.assertTrue(len(res) == 1)
781         self.assertFalse("tokenGroups" in res[0])
782
783         # The domain administrator should contain "tokenGroups" entries
784         # (the exact number depends on the domain/forest function level and the
785         # DC software versions)
786         res = ldb.search("cn=Administrator,cn=Users," + self.base_dn,
787                          scope=SCOPE_BASE, attrs=["tokenGroups"])
788         self.assertTrue(len(res) == 1)
789         self.assertTrue("tokenGroups" in res[0])
790
791         ldb.add({
792             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
793             "objectclass": ["user", "person"]})
794
795         # This testuser should contain at least two "tokenGroups" entries
796         # (exactly two on an unmodified "Domain Users" and "Users" group)
797         res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
798                          scope=SCOPE_BASE, attrs=["tokenGroups"])
799         self.assertTrue(len(res) == 1)
800         self.assertTrue(len(res[0]["tokenGroups"]) >= 2)
801
802         # one entry which we need to find should point to domains "Domain Users"
803         # group and another entry should point to the builtin "Users"group
804         domain_users_group_found = False
805         users_group_found = False
806         for sid in res[0]["tokenGroups"]:
807             rid = security.dom_sid(ldb.schema_format_value("objectSID", sid)).split()[1]
808             if rid == 513:
809                 domain_users_group_found = True
810             if rid == 545:
811                 users_group_found = True
812
813         self.assertTrue(domain_users_group_found)
814         self.assertTrue(users_group_found)
815
816         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
817
818     def test_groupType(self):
819         """Test the groupType behaviour"""
820         print "Testing groupType behaviour\n"
821
822         # You can never create or change to a
823         # "GTYPE_SECURITY_BUILTIN_LOCAL_GROUP"
824
825         # Add operation
826
827         # Invalid attribute
828         try:
829             ldb.add({
830                 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
831                 "objectclass": "group",
832                 "groupType": "0"})
833             self.fail()
834         except LdbError, (num, _):
835             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
836         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
837
838         try:
839             ldb.add({
840                 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
841                 "objectclass": "group",
842                 "groupType": str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP)})
843             self.fail()
844         except LdbError, (num, _):
845             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
846         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
847
848         ldb.add({
849             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
850             "objectclass": "group",
851             "groupType": str(GTYPE_SECURITY_GLOBAL_GROUP)})
852
853         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
854                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
855         self.assertTrue(len(res1) == 1)
856         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
857           ATYPE_SECURITY_GLOBAL_GROUP)
858         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
859
860         ldb.add({
861             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
862             "objectclass": "group",
863             "groupType": str(GTYPE_SECURITY_UNIVERSAL_GROUP)})
864
865         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
866                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
867         self.assertTrue(len(res1) == 1)
868         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
869           ATYPE_SECURITY_UNIVERSAL_GROUP)
870         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
871
872         ldb.add({
873             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
874             "objectclass": "group",
875             "groupType": str(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP)})
876
877         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
878                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
879         self.assertTrue(len(res1) == 1)
880         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
881           ATYPE_SECURITY_LOCAL_GROUP)
882         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
883
884         ldb.add({
885             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
886             "objectclass": "group",
887             "groupType": str(GTYPE_DISTRIBUTION_GLOBAL_GROUP)})
888
889         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
890                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
891         self.assertTrue(len(res1) == 1)
892         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
893           ATYPE_DISTRIBUTION_GLOBAL_GROUP)
894         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
895
896         ldb.add({
897             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
898             "objectclass": "group",
899             "groupType": str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP)})
900
901         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
902                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
903         self.assertTrue(len(res1) == 1)
904         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
905           ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
906         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
907
908         ldb.add({
909             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
910             "objectclass": "group",
911             "groupType": str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)})
912
913         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
914                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
915         self.assertTrue(len(res1) == 1)
916         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
917           ATYPE_DISTRIBUTION_LOCAL_GROUP)
918         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
919
920         # Modify operation
921
922         ldb.add({
923             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
924             "objectclass": "group"})
925
926         # We can change in this direction: global <-> universal <-> local
927         # On each step also the group type itself (security/distribution) is
928         # variable.
929
930         # After creation we should have a "security global group"
931         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
932                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
933         self.assertTrue(len(res1) == 1)
934         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
935           ATYPE_SECURITY_GLOBAL_GROUP)
936
937         # Invalid attribute
938         try:
939             m = Message()
940             m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
941             m["groupType"] = MessageElement("0",
942               FLAG_MOD_REPLACE, "groupType")
943             ldb.modify(m)
944             self.fail()
945         except LdbError, (num, _):
946             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
947
948         # Security groups
949
950         # Default is "global group"
951
952         m = Message()
953         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
954         m["groupType"] = MessageElement(
955           str(GTYPE_SECURITY_GLOBAL_GROUP),
956           FLAG_MOD_REPLACE, "groupType")
957         ldb.modify(m)
958
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         # Change to "local" (shouldn't work)
966
967         try:
968             m = Message()
969             m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
970             m["groupType"] = MessageElement(
971               str(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP),
972               FLAG_MOD_REPLACE, "groupType")
973             ldb.modify(m)
974             self.fail()
975         except LdbError, (num, _):
976             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
977
978         # Change to "universal"
979
980         m = Message()
981         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
982         m["groupType"] = MessageElement(
983          str(GTYPE_SECURITY_UNIVERSAL_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_UNIVERSAL_GROUP)
992
993         # Change back to "global"
994
995         m = Message()
996         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
997         m["groupType"] = MessageElement(
998           str(GTYPE_SECURITY_GLOBAL_GROUP),
999           FLAG_MOD_REPLACE, "groupType")
1000         ldb.modify(m)
1001
1002         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1003                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1004         self.assertTrue(len(res1) == 1)
1005         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1006           ATYPE_SECURITY_GLOBAL_GROUP)
1007
1008         # Change back to "universal"
1009
1010         m = Message()
1011         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1012         m["groupType"] = MessageElement(
1013          str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1014           FLAG_MOD_REPLACE, "groupType")
1015         ldb.modify(m)
1016
1017         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1018                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1019         self.assertTrue(len(res1) == 1)
1020         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1021           ATYPE_SECURITY_UNIVERSAL_GROUP)
1022
1023         # Change to "local"
1024
1025         m = Message()
1026         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1027         m["groupType"] = MessageElement(
1028           str(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP),
1029           FLAG_MOD_REPLACE, "groupType")
1030         ldb.modify(m)
1031
1032         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1033                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1034         self.assertTrue(len(res1) == 1)
1035         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1036           ATYPE_SECURITY_LOCAL_GROUP)
1037
1038         # Change to "global" (shouldn't work)
1039
1040         try:
1041             m = Message()
1042             m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1043             m["groupType"] = MessageElement(
1044               str(GTYPE_SECURITY_GLOBAL_GROUP),
1045               FLAG_MOD_REPLACE, "groupType")
1046             ldb.modify(m)
1047             self.fail()
1048         except LdbError, (num, _):
1049             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1050
1051         # Change to "builtin local" (shouldn't work)
1052
1053         try:
1054             m = Message()
1055             m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1056             m["groupType"] = MessageElement(
1057               str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
1058               FLAG_MOD_REPLACE, "groupType")
1059             ldb.modify(m)
1060             self.fail()
1061         except LdbError, (num, _):
1062             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1063
1064         m = Message()
1065         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1066
1067         # Change back to "universal"
1068
1069         m = Message()
1070         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1071         m["groupType"] = MessageElement(
1072          str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1073           FLAG_MOD_REPLACE, "groupType")
1074         ldb.modify(m)
1075
1076         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1077                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1078         self.assertTrue(len(res1) == 1)
1079         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1080           ATYPE_SECURITY_UNIVERSAL_GROUP)
1081
1082         # Change to "builtin local" (shouldn't work)
1083
1084         try:
1085             m = Message()
1086             m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1087             m["groupType"] = MessageElement(
1088               str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
1089               FLAG_MOD_REPLACE, "groupType")
1090             ldb.modify(m)
1091             self.fail()
1092         except LdbError, (num, _):
1093             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1094
1095         # Change back to "global"
1096
1097         m = Message()
1098         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1099         m["groupType"] = MessageElement(
1100           str(GTYPE_SECURITY_GLOBAL_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_GLOBAL_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         # Distribution groups
1124
1125         # Default is "global group"
1126
1127         m = Message()
1128         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1129         m["groupType"] = MessageElement(
1130           str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1131           FLAG_MOD_REPLACE, "groupType")
1132         ldb.modify(m)
1133
1134         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1135                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1136         self.assertTrue(len(res1) == 1)
1137         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1138           ATYPE_DISTRIBUTION_GLOBAL_GROUP)
1139
1140         # Change to local (shouldn't work)
1141
1142         try:
1143             m = Message()
1144             m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1145             m["groupType"] = MessageElement(
1146               str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1147               FLAG_MOD_REPLACE, "groupType")
1148             ldb.modify(m)
1149             self.fail()
1150         except LdbError, (num, _):
1151             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1152
1153         # Change to "universal"
1154
1155         m = Message()
1156         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1157         m["groupType"] = MessageElement(
1158          str(GTYPE_DISTRIBUTION_UNIVERSAL_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_UNIVERSAL_GROUP)
1167
1168         # Change back to "global"
1169
1170         m = Message()
1171         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1172         m["groupType"] = MessageElement(
1173           str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1174           FLAG_MOD_REPLACE, "groupType")
1175         ldb.modify(m)
1176
1177         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1178                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1179         self.assertTrue(len(res1) == 1)
1180         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1181           ATYPE_DISTRIBUTION_GLOBAL_GROUP)
1182
1183         # Change back to "universal"
1184
1185         m = Message()
1186         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1187         m["groupType"] = MessageElement(
1188          str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1189           FLAG_MOD_REPLACE, "groupType")
1190         ldb.modify(m)
1191
1192         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1193                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1194         self.assertTrue(len(res1) == 1)
1195         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1196           ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1197
1198         # Change to "local"
1199
1200         m = Message()
1201         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1202         m["groupType"] = MessageElement(
1203           str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1204           FLAG_MOD_REPLACE, "groupType")
1205         ldb.modify(m)
1206
1207         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1208                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1209         self.assertTrue(len(res1) == 1)
1210         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1211           ATYPE_DISTRIBUTION_LOCAL_GROUP)
1212
1213         # Change to "global" (shouldn't work)
1214
1215         try:
1216             m = Message()
1217             m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1218             m["groupType"] = MessageElement(
1219               str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1220               FLAG_MOD_REPLACE, "groupType")
1221             ldb.modify(m)
1222             self.fail()
1223         except LdbError, (num, _):
1224             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1225
1226         # Change back to "universal"
1227
1228         # Try to add invalid member to group 1 - should be denied
1229         m = Message()
1230         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1231         m["member"] = MessageElement(
1232           "cn=ldaptestuser3,cn=users," + self.base_dn,
1233           FLAG_MOD_ADD, "member")
1234         try:
1235             ldb.modify(m)
1236             self.fail()
1237         except LdbError, (num, _):
1238             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1239
1240         # Make group 2 secondary
1241         m = Message()
1242         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1243         m["groupType"] = MessageElement(
1244          str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1245           FLAG_MOD_REPLACE, "groupType")
1246         ldb.modify(m)
1247
1248         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1249                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1250         self.assertTrue(len(res1) == 1)
1251         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1252           ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1253
1254         # Change back to "global"
1255
1256         m = Message()
1257         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1258         m["groupType"] = MessageElement(
1259           str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1260           FLAG_MOD_REPLACE, "groupType")
1261         ldb.modify(m)
1262
1263         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1264                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1265         self.assertTrue(len(res1) == 1)
1266         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1267           ATYPE_DISTRIBUTION_GLOBAL_GROUP)
1268
1269         # Both group types: this performs only random checks - all possibilities
1270         # would require too much code.
1271
1272         # Default is "global group"
1273
1274         m = Message()
1275         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1276         m["groupType"] = MessageElement(
1277           str(GTYPE_SECURITY_GLOBAL_GROUP),
1278           FLAG_MOD_REPLACE, "groupType")
1279         ldb.modify(m)
1280
1281         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1282                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1283         self.assertTrue(len(res1) == 1)
1284         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1285           ATYPE_SECURITY_GLOBAL_GROUP)
1286
1287         # Change to "local" (shouldn't work)
1288
1289         try:
1290             m = Message()
1291             m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1292             m["groupType"] = MessageElement(
1293               str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1294               FLAG_MOD_REPLACE, "groupType")
1295             ldb.modify(m)
1296             self.fail()
1297         except LdbError, (num, _):
1298             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1299
1300         # Change to "universal"
1301
1302         m = Message()
1303         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1304         m["groupType"] = MessageElement(
1305          str(GTYPE_DISTRIBUTION_UNIVERSAL_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_DISTRIBUTION_UNIVERSAL_GROUP)
1314
1315         # Change back to "global"
1316
1317         m = Message()
1318         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1319         m["groupType"] = MessageElement(
1320           str(GTYPE_SECURITY_GLOBAL_GROUP),
1321           FLAG_MOD_REPLACE, "groupType")
1322         ldb.modify(m)
1323
1324         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1325                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1326         self.assertTrue(len(res1) == 1)
1327         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1328           ATYPE_SECURITY_GLOBAL_GROUP)
1329
1330         # Change back to "universal"
1331
1332         m = Message()
1333         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1334         m["groupType"] = MessageElement(
1335          str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1336           FLAG_MOD_REPLACE, "groupType")
1337         ldb.modify(m)
1338
1339         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1340                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1341         self.assertTrue(len(res1) == 1)
1342         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1343           ATYPE_SECURITY_UNIVERSAL_GROUP)
1344
1345         # Change to "local"
1346
1347         m = Message()
1348         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1349         m["groupType"] = MessageElement(
1350           str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1351           FLAG_MOD_REPLACE, "groupType")
1352         ldb.modify(m)
1353
1354         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1355                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1356         self.assertTrue(len(res1) == 1)
1357         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1358           ATYPE_DISTRIBUTION_LOCAL_GROUP)
1359
1360         # Change to "global" (shouldn't work)
1361
1362         try:
1363             m = Message()
1364             m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1365             m["groupType"] = MessageElement(
1366               str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1367               FLAG_MOD_REPLACE, "groupType")
1368             ldb.modify(m)
1369             self.fail()
1370         except LdbError, (num, _):
1371             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1372
1373         # Change back to "universal"
1374
1375         m = Message()
1376         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1377         m["groupType"] = MessageElement(
1378          str(GTYPE_SECURITY_UNIVERSAL_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_SECURITY_UNIVERSAL_GROUP)
1387
1388         # Change back to "global"
1389
1390         m = Message()
1391         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1392         m["groupType"] = MessageElement(
1393           str(GTYPE_SECURITY_GLOBAL_GROUP),
1394           FLAG_MOD_REPLACE, "groupType")
1395         ldb.modify(m)
1396
1397         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1398                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1399         self.assertTrue(len(res1) == 1)
1400         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1401           ATYPE_SECURITY_GLOBAL_GROUP)
1402
1403         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1404
1405     def test_userAccountControl(self):
1406         """Test the userAccountControl behaviour"""
1407         print "Testing userAccountControl behaviour\n"
1408
1409         # With a user object
1410
1411         # Add operation
1412
1413         # As user you can only set a normal account.
1414         # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
1415         # password yet.
1416         # With SYSTEM rights you can set a interdomain trust account.
1417
1418         # Invalid attribute
1419         try:
1420             ldb.add({
1421                 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1422                 "objectclass": ["user", "person"],
1423                 "userAccountControl": "0"})
1424             self.fail()
1425         except LdbError, (num, _):
1426             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1427         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1428
1429 # This has to wait until s4 supports it (needs a password module change)
1430 #        try:
1431 #            ldb.add({
1432 #                "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1433 #                "objectclass": ["user", "person"],
1434 #                "userAccountControl": str(UF_NORMAL_ACCOUNT)})
1435 #            self.fail()
1436 #        except LdbError, (num, _):
1437 #            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1438 #        self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1439
1440         ldb.add({
1441             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1442             "objectclass": ["user", "person"],
1443             "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD)})
1444
1445         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1446                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1447         self.assertTrue(len(res1) == 1)
1448         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1449           ATYPE_NORMAL_ACCOUNT)
1450         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1451
1452         try:
1453             ldb.add({
1454                 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1455                 "objectclass": ["user", "person"],
1456                 "userAccountControl": str(UF_TEMP_DUPLICATE_ACCOUNT)})
1457             self.fail()
1458         except LdbError, (num, _):
1459             self.assertEquals(num, ERR_OTHER)
1460         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1461
1462 # This isn't supported yet in s4
1463 #        try:
1464 #            ldb.add({
1465 #                "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1466 #                "objectclass": ["user", "person"],
1467 #                "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT)})
1468 #            self.fail()
1469 #        except LdbError, (num, _):
1470 #            self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
1471 #        self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1472 #
1473 #        try:
1474 #            ldb.add({
1475 #                "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1476 #                "objectclass": ["user", "person"],
1477 #                "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT)})
1478 #        except LdbError, (num, _):
1479 #            self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
1480 #        self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1481
1482 # This isn't supported yet in s4 - needs ACL module adaption
1483 #        try:
1484 #            ldb.add({
1485 #                "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1486 #                "objectclass": ["user", "person"],
1487 #                "userAccountControl": str(UF_INTERDOMAIN_TRUST_ACCOUNT)})
1488 #            self.fail()
1489 #        except LdbError, (num, _):
1490 #            self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1491 #        self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1492
1493         # Modify operation
1494
1495         ldb.add({
1496             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1497             "objectclass": ["user", "person"]})
1498
1499         # After creation we should have a normal account
1500         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1501                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1502         self.assertTrue(len(res1) == 1)
1503         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1504           ATYPE_NORMAL_ACCOUNT)
1505
1506         # As user you can only switch from a normal account to a workstation
1507         # trust account and back.
1508         # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
1509         # password yet.
1510         # With SYSTEM rights you can switch to a interdomain trust account.
1511
1512         # Invalid attribute
1513         try:
1514             m = Message()
1515             m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1516             m["userAccountControl"] = MessageElement("0",
1517               FLAG_MOD_REPLACE, "userAccountControl")
1518             ldb.modify(m)
1519         except LdbError, (num, _):
1520             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1521
1522 # This has to wait until s4 supports it (needs a password module change)
1523 #        try:
1524 #            m = Message()
1525 #            m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1526 #            m["userAccountControl"] = MessageElement(
1527 #              str(UF_NORMAL_ACCOUNT),
1528 #              FLAG_MOD_REPLACE, "userAccountControl")
1529 #            ldb.modify(m)
1530 #        except LdbError, (num, _):
1531 #            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1532
1533         m = Message()
1534         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1535         m["userAccountControl"] = MessageElement(
1536           str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
1537           FLAG_MOD_REPLACE, "userAccountControl")
1538         ldb.modify(m)
1539
1540         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1541                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1542         self.assertTrue(len(res1) == 1)
1543         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1544           ATYPE_NORMAL_ACCOUNT)
1545
1546         try:
1547             m = Message()
1548             m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1549             m["userAccountControl"] = MessageElement(
1550               str(UF_TEMP_DUPLICATE_ACCOUNT),
1551               FLAG_MOD_REPLACE, "userAccountControl")
1552             ldb.modify(m)
1553             self.fail()
1554         except LdbError, (num, _):
1555             self.assertEquals(num, ERR_OTHER)
1556
1557 # This isn't supported yet in s4
1558 #        try:
1559 #            m = Message()
1560 #            m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1561 #            m["userAccountControl"] = MessageElement(
1562 #              str(UF_SERVER_TRUST_ACCOUNT),
1563 #              FLAG_MOD_REPLACE, "userAccountControl")
1564 #            ldb.modify(m)
1565 #            self.fail()
1566 #        except LdbError, (num, _):
1567 #            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1568
1569         m = Message()
1570         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1571         m["userAccountControl"] = MessageElement(
1572           str(UF_WORKSTATION_TRUST_ACCOUNT),
1573           FLAG_MOD_REPLACE, "userAccountControl")
1574         ldb.modify(m)
1575
1576         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1577                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1578         self.assertTrue(len(res1) == 1)
1579         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1580           ATYPE_WORKSTATION_TRUST)
1581
1582         m = Message()
1583         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1584         m["userAccountControl"] = MessageElement(
1585           str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
1586           FLAG_MOD_REPLACE, "userAccountControl")
1587         ldb.modify(m)
1588
1589         res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1590                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1591         self.assertTrue(len(res1) == 1)
1592         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1593           ATYPE_NORMAL_ACCOUNT)
1594
1595 # This isn't supported yet in s4 - needs ACL module adaption
1596 #        try:
1597 #            m = Message()
1598 #            m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1599 #            m["userAccountControl"] = MessageElement(
1600 #              str(UF_INTERDOMAIN_TRUST_ACCOUNT),
1601 #              FLAG_MOD_REPLACE, "userAccountControl")
1602 #            ldb.modify(m)
1603 #            self.fail()
1604 #        except LdbError, (num, _):
1605 #            self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1606
1607         # With a computer object
1608
1609         # Add operation
1610
1611         # As computer you can set a normal account and a server trust account.
1612         # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
1613         # password yet.
1614         # With SYSTEM rights you can set a interdomain trust account.
1615
1616         # Invalid attribute
1617         try:
1618             ldb.add({
1619                 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1620                 "objectclass": ["computer"],
1621                 "userAccountControl": "0"})
1622             self.fail()
1623         except LdbError, (num, _):
1624             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1625         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1626
1627 # This has to wait until s4 supports it (needs a password module change)
1628 #        try:
1629 #            ldb.add({
1630 #                "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1631 #                "objectclass": ["computer"],
1632 #                "userAccountControl": str(UF_NORMAL_ACCOUNT)})
1633 #            self.fail()
1634 #        except LdbError, (num, _):
1635 #            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1636 #        self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1637
1638         ldb.add({
1639             "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1640             "objectclass": ["computer"],
1641             "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD)})
1642
1643         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1644                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1645         self.assertTrue(len(res1) == 1)
1646         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1647           ATYPE_NORMAL_ACCOUNT)
1648         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1649
1650         try:
1651             ldb.add({
1652                 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1653                 "objectclass": ["computer"],
1654                 "userAccountControl": str(UF_TEMP_DUPLICATE_ACCOUNT)})
1655             self.fail()
1656         except LdbError, (num, _):
1657             self.assertEquals(num, ERR_OTHER)
1658         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1659
1660         ldb.add({
1661             "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1662             "objectclass": ["computer"],
1663             "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT)})
1664
1665         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1666                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1667         self.assertTrue(len(res1) == 1)
1668         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1669           ATYPE_WORKSTATION_TRUST)
1670         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1671
1672         try:
1673             ldb.add({
1674                 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1675                 "objectclass": ["computer"],
1676                 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT)})
1677         except LdbError, (num, _):
1678             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
1679         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1680
1681 # This isn't supported yet in s4 - needs ACL module adaption
1682 #        try:
1683 #            ldb.add({
1684 #                "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1685 #                "objectclass": ["computer"],
1686 #                "userAccountControl": str(UF_INTERDOMAIN_TRUST_ACCOUNT)})
1687 #            self.fail()
1688 #        except LdbError, (num, _):
1689 #            self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1690 #        self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1691
1692         # Modify operation
1693
1694         ldb.add({
1695             "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1696             "objectclass": ["computer"]})
1697
1698         # After creation we should have a normal account
1699         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1700                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1701         self.assertTrue(len(res1) == 1)
1702         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1703           ATYPE_NORMAL_ACCOUNT)
1704
1705         # As computer you can switch from a normal account to a workstation
1706         # or server trust account and back (also swapping between trust
1707         # accounts is allowed).
1708         # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
1709         # password yet.
1710         # With SYSTEM rights you can switch to a interdomain trust account.
1711
1712         # Invalid attribute
1713         try:
1714             m = Message()
1715             m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1716             m["userAccountControl"] = MessageElement("0",
1717               FLAG_MOD_REPLACE, "userAccountControl")
1718             ldb.modify(m)
1719         except LdbError, (num, _):
1720             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1721
1722 # This has to wait until s4 supports it (needs a password module change)
1723 #        try:
1724 #            m = Message()
1725 #            m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1726 #            m["userAccountControl"] = MessageElement(
1727 #              str(UF_NORMAL_ACCOUNT),
1728 #              FLAG_MOD_REPLACE, "userAccountControl")
1729 #            ldb.modify(m)
1730 #        except LdbError, (num, _):
1731 #            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1732
1733         m = Message()
1734         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1735         m["userAccountControl"] = MessageElement(
1736           str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
1737           FLAG_MOD_REPLACE, "userAccountControl")
1738         ldb.modify(m)
1739
1740         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1741                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1742         self.assertTrue(len(res1) == 1)
1743         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1744           ATYPE_NORMAL_ACCOUNT)
1745
1746         try:
1747             m = Message()
1748             m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1749             m["userAccountControl"] = MessageElement(
1750               str(UF_TEMP_DUPLICATE_ACCOUNT),
1751               FLAG_MOD_REPLACE, "userAccountControl")
1752             ldb.modify(m)
1753             self.fail()
1754         except LdbError, (num, _):
1755             self.assertEquals(num, ERR_OTHER)
1756
1757         m = Message()
1758         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1759         m["userAccountControl"] = MessageElement(
1760           str(UF_SERVER_TRUST_ACCOUNT),
1761           FLAG_MOD_REPLACE, "userAccountControl")
1762         ldb.modify(m)
1763
1764         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1765                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1766         self.assertTrue(len(res1) == 1)
1767         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1768           ATYPE_WORKSTATION_TRUST)
1769
1770         m = Message()
1771         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1772         m["userAccountControl"] = MessageElement(
1773           str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
1774           FLAG_MOD_REPLACE, "userAccountControl")
1775         ldb.modify(m)
1776
1777         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1778                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1779         self.assertTrue(len(res1) == 1)
1780         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1781           ATYPE_NORMAL_ACCOUNT)
1782
1783         m = Message()
1784         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1785         m["userAccountControl"] = MessageElement(
1786           str(UF_WORKSTATION_TRUST_ACCOUNT),
1787           FLAG_MOD_REPLACE, "userAccountControl")
1788         ldb.modify(m)
1789
1790         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1791                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1792         self.assertTrue(len(res1) == 1)
1793         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1794           ATYPE_WORKSTATION_TRUST)
1795
1796         m = Message()
1797         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1798         m["userAccountControl"] = MessageElement(
1799           str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
1800           FLAG_MOD_REPLACE, "userAccountControl")
1801         ldb.modify(m)
1802
1803         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1804                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1805         self.assertTrue(len(res1) == 1)
1806         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1807           ATYPE_NORMAL_ACCOUNT)
1808
1809         m = Message()
1810         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1811         m["userAccountControl"] = MessageElement(
1812           str(UF_SERVER_TRUST_ACCOUNT),
1813           FLAG_MOD_REPLACE, "userAccountControl")
1814         ldb.modify(m)
1815
1816         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1817                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1818         self.assertTrue(len(res1) == 1)
1819         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1820           ATYPE_WORKSTATION_TRUST)
1821
1822         m = Message()
1823         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1824         m["userAccountControl"] = MessageElement(
1825           str(UF_WORKSTATION_TRUST_ACCOUNT),
1826           FLAG_MOD_REPLACE, "userAccountControl")
1827         ldb.modify(m)
1828
1829         res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1830                           scope=SCOPE_BASE, attrs=["sAMAccountType"])
1831         self.assertTrue(len(res1) == 1)
1832         self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1833           ATYPE_WORKSTATION_TRUST)
1834
1835 # This isn't supported yet in s4 - needs ACL module adaption
1836 #        try:
1837 #            m = Message()
1838 #            m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1839 #            m["userAccountControl"] = MessageElement(
1840 #              str(UF_INTERDOMAIN_TRUST_ACCOUNT),
1841 #              FLAG_MOD_REPLACE, "userAccountControl")
1842 #            ldb.modify(m)
1843 #            self.fail()
1844 #        except LdbError, (num, _):
1845 #            self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1846
1847         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1848         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1849
1850     def test_dNSHostName(self):
1851         """Test the dNSHostName behaviour"""
1852         print "Testing dNSHostName behaviour\n"
1853
1854         ldb.add({
1855             "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1856             "objectclass": "computer",
1857             "dNSHostName": "testname.testdom"})
1858
1859         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1860                           scope=SCOPE_BASE, attrs=["servicePrincipalName"])
1861         self.assertTrue(len(res) == 1)
1862         self.assertFalse("servicePrincipalName" in res[0])
1863
1864         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1865
1866         ldb.add({
1867             "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1868             "objectclass": "computer",
1869             "servicePrincipalName": "HOST/testname.testdom"})
1870
1871         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1872                           scope=SCOPE_BASE, attrs=["dNSHostName"])
1873         self.assertTrue(len(res) == 1)
1874         self.assertFalse("dNSHostName" in res[0])
1875
1876         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1877
1878         ldb.add({
1879             "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1880             "objectclass": "computer",
1881             "dNSHostName": "testname2.testdom",
1882             "servicePrincipalName": "HOST/testname.testdom"})
1883
1884         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1885                           scope=SCOPE_BASE, attrs=["dNSHostName"])
1886         self.assertTrue(len(res) == 1)
1887         self.assertEquals(res[0]["dNSHostName"][0], "testname2.testdom")
1888
1889         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1890                           scope=SCOPE_BASE, attrs=["servicePrincipalName"])
1891         self.assertTrue(len(res) == 1)
1892         self.assertEquals(res[0]["servicePrincipalName"][0],
1893                           "HOST/testname.testdom")
1894
1895         m = Message()
1896         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1897         m["dNSHostName"] = MessageElement("testname.testdoM",
1898                                           FLAG_MOD_REPLACE, "dNSHostName")
1899         ldb.modify(m)
1900
1901         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1902                           scope=SCOPE_BASE, attrs=["servicePrincipalName"])
1903         self.assertTrue(len(res) == 1)
1904         self.assertEquals(res[0]["servicePrincipalName"][0],
1905                           "HOST/testname.testdom")
1906
1907         m = Message()
1908         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1909         m["dNSHostName"] = MessageElement("testname2.testdom2",
1910                                           FLAG_MOD_REPLACE, "dNSHostName")
1911         ldb.modify(m)
1912
1913         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1914                           scope=SCOPE_BASE, attrs=["servicePrincipalName"])
1915         self.assertTrue(len(res) == 1)
1916         self.assertEquals(res[0]["servicePrincipalName"][0],
1917                           "HOST/testname2.testdom2")
1918
1919         m = Message()
1920         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1921         m["dNSHostName"] = MessageElement([],
1922                                           FLAG_MOD_DELETE, "dNSHostName")
1923         ldb.modify(m)
1924
1925         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1926                           scope=SCOPE_BASE, attrs=["servicePrincipalName"])
1927         self.assertTrue(len(res) == 1)
1928         self.assertEquals(res[0]["servicePrincipalName"][0],
1929                           "HOST/testname2.testdom2")
1930
1931         m = Message()
1932         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1933         m["dNSHostName"] = MessageElement("testname.testdom3",
1934                                           FLAG_MOD_REPLACE, "dNSHostName")
1935         ldb.modify(m)
1936
1937         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1938                           scope=SCOPE_BASE, attrs=["servicePrincipalName"])
1939         self.assertTrue(len(res) == 1)
1940         self.assertEquals(res[0]["servicePrincipalName"][0],
1941                           "HOST/testname2.testdom2")
1942
1943         m = Message()
1944         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1945         m["dNSHostName"] = MessageElement("testname2.testdom2",
1946                                           FLAG_MOD_REPLACE, "dNSHostName")
1947         ldb.modify(m)
1948
1949         m = Message()
1950         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1951         m["dNSHostName"] = MessageElement("testname3.testdom3",
1952                                           FLAG_MOD_REPLACE, "dNSHostName")
1953         m["servicePrincipalName"] = MessageElement("HOST/testname2.testdom2",
1954                                                    FLAG_MOD_REPLACE,
1955                                                    "servicePrincipalName")
1956         ldb.modify(m)
1957
1958         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1959                           scope=SCOPE_BASE, attrs=["servicePrincipalName"])
1960         self.assertTrue(len(res) == 1)
1961         self.assertEquals(res[0]["servicePrincipalName"][0],
1962                           "HOST/testname3.testdom3")
1963
1964         m = Message()
1965         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1966         m["servicePrincipalName"] = MessageElement("HOST/testname2.testdom2",
1967                                                    FLAG_MOD_REPLACE,
1968                                                    "servicePrincipalName")
1969         m["dNSHostName"] = MessageElement("testname4.testdom4",
1970                                           FLAG_MOD_REPLACE, "dNSHostName")
1971         ldb.modify(m)
1972
1973         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1974                           scope=SCOPE_BASE, attrs=["servicePrincipalName"])
1975         self.assertTrue(len(res) == 1)
1976         self.assertEquals(res[0]["servicePrincipalName"][0],
1977                           "HOST/testname2.testdom2")
1978
1979         m = Message()
1980         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1981         m["servicePrincipalName"] = MessageElement([],
1982                                                    FLAG_MOD_DELETE,
1983                                                    "servicePrincipalName")
1984         ldb.modify(m)
1985
1986         m = Message()
1987         m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1988         m["dNSHostName"] = MessageElement("testname2.testdom2",
1989                                           FLAG_MOD_REPLACE, "dNSHostName")
1990         ldb.modify(m)
1991
1992         res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1993                           scope=SCOPE_BASE, attrs=["servicePrincipalName"])
1994         self.assertTrue(len(res) == 1)
1995         self.assertFalse("servicePrincipalName" in res[0])
1996
1997         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1998
1999
2000 if not "://" in host:
2001     if os.path.isfile(host):
2002         host = "tdb://%s" % host
2003     else:
2004         host = "ldap://%s" % host
2005
2006 ldb = Ldb(host, credentials=creds, session_info=system_session(), lp=lp)
2007 if not "tdb://" in host:
2008     gc_ldb = Ldb("%s:3268" % host, credentials=creds,
2009                  session_info=system_session(), lp=lp)
2010 else:
2011     gc_ldb = None
2012
2013 runner = SubunitTestRunner()
2014 rc = 0
2015 if not runner.run(unittest.makeSuite(SamTests)).wasSuccessful():
2016     rc = 1
2017 sys.exit(rc)