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