2 # -*- coding: utf-8 -*-
3 # This tests the restrictions on userAccountControl that apply even if write access is permitted
5 # Copyright Samuel Cabrero 2014 <samuelcabrero@kernevil.me>
6 # Copyright Andrew Bartlett 2014 <abartlet@samba.org>
8 # Licenced under the GPLv3
15 import samba
.getopt
as options
20 sys
.path
.insert(0, "bin/python")
21 from samba
.tests
.subunitrun
import TestProgram
, SubunitOptions
23 from subunit
.run
import SubunitTestRunner
24 from samba
.auth
import system_session
25 from samba
.samdb
import SamDB
26 from samba
.dcerpc
import samr
, security
, lsa
27 from samba
.credentials
import Credentials
28 from samba
.ndr
import ndr_unpack
, ndr_pack
29 from samba
.tests
import delete_force
30 from samba
import gensec
, sd_utils
31 from samba
.credentials
import DONT_USE_KERBEROS
32 from ldb
import SCOPE_SUBTREE
, SCOPE_BASE
, LdbError
33 from ldb
import Message
, MessageElement
, Dn
34 from ldb
import FLAG_MOD_ADD
, FLAG_MOD_REPLACE
, FLAG_MOD_DELETE
35 from samba
.dsdb
import UF_SCRIPT
, UF_ACCOUNTDISABLE
, UF_00000004
, UF_HOMEDIR_REQUIRED
, \
36 UF_LOCKOUT
,UF_PASSWD_NOTREQD
, UF_PASSWD_CANT_CHANGE
, UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED
,\
37 UF_TEMP_DUPLICATE_ACCOUNT
, UF_NORMAL_ACCOUNT
, UF_00000400
, UF_INTERDOMAIN_TRUST_ACCOUNT
, \
38 UF_WORKSTATION_TRUST_ACCOUNT
, UF_SERVER_TRUST_ACCOUNT
, UF_00004000
, \
39 UF_00008000
, UF_DONT_EXPIRE_PASSWD
, UF_MNS_LOGON_ACCOUNT
, UF_SMARTCARD_REQUIRED
, \
40 UF_TRUSTED_FOR_DELEGATION
, UF_NOT_DELEGATED
, UF_USE_DES_KEY_ONLY
, UF_DONT_REQUIRE_PREAUTH
, \
41 UF_PASSWORD_EXPIRED
, UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
, UF_NO_AUTH_DATA_REQUIRED
, \
42 UF_PARTIAL_SECRETS_ACCOUNT
, UF_USE_AES_KEYS
45 parser
= optparse
.OptionParser("machine_account_privilege.py [options] <host>")
46 sambaopts
= options
.SambaOptions(parser
)
47 parser
.add_option_group(sambaopts
)
48 parser
.add_option_group(options
.VersionOptions(parser
))
50 # use command line creds if available
51 credopts
= options
.CredentialsOptions(parser
)
52 parser
.add_option_group(credopts
)
53 opts
, args
= parser
.parse_args()
61 ldaphost
= "ldap://%s" % host
64 start
= host
.rindex("://")
65 host
= host
.lstrip(start
+3)
67 lp
= sambaopts
.get_loadparm()
68 creds
= credopts
.get_credentials(lp
)
69 creds
.set_gensec_features(creds
.get_gensec_features() | gensec
.FEATURE_SEAL
)
71 bits
= [UF_SCRIPT
, UF_ACCOUNTDISABLE
, UF_00000004
, UF_HOMEDIR_REQUIRED
,
72 UF_LOCKOUT
,UF_PASSWD_NOTREQD
, UF_PASSWD_CANT_CHANGE
,
73 UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED
,
74 UF_TEMP_DUPLICATE_ACCOUNT
, UF_NORMAL_ACCOUNT
, UF_00000400
,
75 UF_INTERDOMAIN_TRUST_ACCOUNT
,
76 UF_WORKSTATION_TRUST_ACCOUNT
, UF_SERVER_TRUST_ACCOUNT
, UF_00004000
,
77 UF_00008000
, UF_DONT_EXPIRE_PASSWD
, UF_MNS_LOGON_ACCOUNT
, UF_SMARTCARD_REQUIRED
,
78 UF_TRUSTED_FOR_DELEGATION
, UF_NOT_DELEGATED
, UF_USE_DES_KEY_ONLY
,
79 UF_DONT_REQUIRE_PREAUTH
,
80 UF_PASSWORD_EXPIRED
, UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
,
81 UF_NO_AUTH_DATA_REQUIRED
,
82 UF_PARTIAL_SECRETS_ACCOUNT
, UF_USE_AES_KEYS
,
83 int("0x10000000", 16), int("0x20000000", 16), int("0x40000000", 16), int("0x80000000", 16)]
86 class UserAccountControlTests(samba
.tests
.TestCase
):
87 def add_computer_ldap(self
, computername
, others
=None, samdb
=None):
90 dn
= "CN=%s,OU=test_computer_ou1,%s" % (computername
, self
.base_dn
)
91 domainname
= ldb
.Dn(self
.samdb
, self
.samdb
.domain_dn()).canonical_str().replace("/", "")
92 samaccountname
= "%s$" % computername
93 dnshostname
= "%s.%s" % (computername
, domainname
)
96 "objectclass": "computer"}
97 if others
is not None:
98 msg_dict
= dict(msg_dict
.items() + others
.items())
100 msg
= ldb
.Message
.from_dict(self
.samdb
, msg_dict
)
101 msg
["sAMAccountName"] = samaccountname
103 print "Adding computer account %s" % computername
106 def get_creds(self
, target_username
, target_password
):
107 creds_tmp
= Credentials()
108 creds_tmp
.set_username(target_username
)
109 creds_tmp
.set_password(target_password
)
110 creds_tmp
.set_domain(creds
.get_domain())
111 creds_tmp
.set_realm(creds
.get_realm())
112 creds_tmp
.set_workstation(creds
.get_workstation())
113 creds_tmp
.set_gensec_features(creds_tmp
.get_gensec_features()
114 | gensec
.FEATURE_SEAL
)
115 creds_tmp
.set_kerberos_state(DONT_USE_KERBEROS
) # kinit is too expensive to use in a tight loop
119 super(UserAccountControlTests
, self
).setUp()
120 self
.admin_creds
= creds
121 self
.admin_samdb
= SamDB(url
=ldaphost
,
122 session_info
=system_session(),
123 credentials
=self
.admin_creds
, lp
=lp
)
125 self
.unpriv_user
= "testuser1"
126 self
.unpriv_user_pw
= "samba123@"
127 self
.unpriv_creds
= self
.get_creds(self
.unpriv_user
, self
.unpriv_user_pw
)
129 self
.admin_samdb
.newuser(self
.unpriv_user
, self
.unpriv_user_pw
)
130 res
= self
.admin_samdb
.search("CN=%s,CN=Users,%s" % (self
.unpriv_user
, self
.admin_samdb
.domain_dn()),
133 self
.assertEqual(1, len(res
))
135 self
.unpriv_user_sid
= ndr_unpack(security
.dom_sid
, res
[0]["objectSid"][0])
136 self
.unpriv_user_dn
= res
[0].dn
138 self
.samdb
= SamDB(url
=ldaphost
, credentials
=self
.unpriv_creds
, lp
=lp
)
139 self
.domain_sid
= security
.dom_sid(self
.samdb
.get_domain_sid())
140 self
.base_dn
= self
.samdb
.domain_dn()
142 self
.samr
= samr
.samr("ncacn_ip_tcp:%s[sign]" % host
, lp
, self
.unpriv_creds
)
143 self
.samr_handle
= self
.samr
.Connect2(None, security
.SEC_FLAG_MAXIMUM_ALLOWED
)
144 self
.samr_domain
= self
.samr
.OpenDomain(self
.samr_handle
, security
.SEC_FLAG_MAXIMUM_ALLOWED
, self
.domain_sid
)
146 self
.sd_utils
= sd_utils
.SDUtils(self
.admin_samdb
)
148 self
.admin_samdb
.create_ou("OU=test_computer_ou1," + self
.base_dn
)
149 self
.unpriv_user_sid
= self
.sd_utils
.get_object_sid(self
.unpriv_user_dn
)
150 mod
= "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(self
.unpriv_user_sid
)
152 old_sd
= self
.sd_utils
.read_sd_on_dn("OU=test_computer_ou1," + self
.base_dn
)
154 self
.sd_utils
.dacl_add_ace("OU=test_computer_ou1," + self
.base_dn
, mod
)
156 self
.add_computer_ldap("testcomputer-t")
158 self
.sd_utils
.modify_sd_on_dn("OU=test_computer_ou1," + self
.base_dn
, old_sd
)
160 self
.computernames
= ["testcomputer-0"]
162 # Get the SD of the template account, then force it to match
163 # what we expect for SeMachineAccountPrivilege accounts, so we
164 # can confirm we created the accounts correctly
165 self
.sd_reference_cc
= self
.sd_utils
.read_sd_on_dn("CN=testcomputer-t,OU=test_computer_ou1,%s" % (self
.base_dn
))
167 self
.sd_reference_modify
= self
.sd_utils
.read_sd_on_dn("CN=testcomputer-t,OU=test_computer_ou1,%s" % (self
.base_dn
))
168 for ace
in self
.sd_reference_modify
.dacl
.aces
:
169 if ace
.type == security
.SEC_ACE_TYPE_ACCESS_ALLOWED
and ace
.trustee
== self
.unpriv_user_sid
:
170 ace
.access_mask
= ace
.access_mask | security
.SEC_ADS_SELF_WRITE | security
.SEC_ADS_WRITE_PROP
172 # Now reconnect without domain admin rights
173 self
.samdb
= SamDB(url
=ldaphost
, credentials
=self
.unpriv_creds
, lp
=lp
)
177 super(UserAccountControlTests
, self
).tearDown()
178 for computername
in self
.computernames
:
179 delete_force(self
.admin_samdb
, "CN=%s,OU=test_computer_ou1,%s" % (computername
, self
.base_dn
))
180 delete_force(self
.admin_samdb
, "CN=testcomputer-t,OU=test_computer_ou1,%s" % (self
.base_dn
))
181 delete_force(self
.admin_samdb
, "OU=test_computer_ou1,%s" % (self
.base_dn
))
182 delete_force(self
.admin_samdb
, "CN=%s,CN=Users,%s" % (self
.unpriv_user
, self
.base_dn
))
184 def test_add_computer_sd_cc(self
):
185 user_sid
= self
.sd_utils
.get_object_sid(self
.unpriv_user_dn
)
186 mod
= "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid
)
188 old_sd
= self
.sd_utils
.read_sd_on_dn("OU=test_computer_ou1," + self
.base_dn
)
190 self
.sd_utils
.dacl_add_ace("OU=test_computer_ou1," + self
.base_dn
, mod
)
192 computername
=self
.computernames
[0]
193 sd
= ldb
.MessageElement((ndr_pack(self
.sd_reference_modify
)),
195 "nTSecurityDescriptor")
196 self
.add_computer_ldap(computername
,
197 others
={"nTSecurityDescriptor": sd
})
199 res
= self
.admin_samdb
.search("%s" % self
.base_dn
,
200 expression
="(&(objectClass=computer)(samAccountName=%s$))" % computername
,
202 attrs
=["ntSecurityDescriptor"])
204 desc
= res
[0]["nTSecurityDescriptor"][0]
205 desc
= ndr_unpack(security
.descriptor
, desc
, allow_remaining
=True)
207 sddl
= desc
.as_sddl(self
.domain_sid
)
208 self
.assertEqual(self
.sd_reference_modify
.as_sddl(self
.domain_sid
), sddl
)
212 m
["description"]= ldb
.MessageElement(
213 ("A description"), ldb
.FLAG_MOD_REPLACE
,
219 m
["userAccountControl"] = ldb
.MessageElement(str(samba
.dsdb
.UF_SERVER_TRUST_ACCOUNT
),
220 ldb
.FLAG_MOD_REPLACE
, "userAccountControl")
223 self
.fail("Unexpectedly able to set userAccountControl to be a DC on %s" % m
.dn
)
224 except LdbError
, (enum
, estr
):
225 self
.assertEqual(ldb
.ERR_INSUFFICIENT_ACCESS_RIGHTS
, enum
)
229 m
["userAccountControl"] = ldb
.MessageElement(str(samba
.dsdb
.UF_WORKSTATION_TRUST_ACCOUNT|samba
.dsdb
.UF_PARTIAL_SECRETS_ACCOUNT
),
230 ldb
.FLAG_MOD_REPLACE
, "userAccountControl")
233 self
.fail("Unexpectedly able to set userAccountControl to be an RODC on %s" % m
.dn
)
234 except LdbError
, (enum
, estr
):
235 self
.assertEqual(ldb
.ERR_INSUFFICIENT_ACCESS_RIGHTS
, enum
)
239 m
["userAccountControl"] = ldb
.MessageElement(str(samba
.dsdb
.UF_WORKSTATION_TRUST_ACCOUNT
),
240 ldb
.FLAG_MOD_REPLACE
, "userAccountControl")
245 m
["primaryGroupID"] = ldb
.MessageElement(str(security
.DOMAIN_RID_ADMINS
),
246 ldb
.FLAG_MOD_REPLACE
, "primaryGroupID")
249 except LdbError
, (enum
, estr
):
250 self
.assertEqual(ldb
.ERR_UNWILLING_TO_PERFORM
, enum
)
254 def test_mod_computer_cc(self
):
255 user_sid
= self
.sd_utils
.get_object_sid(self
.unpriv_user_dn
)
256 mod
= "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid
)
258 old_sd
= self
.sd_utils
.read_sd_on_dn("OU=test_computer_ou1," + self
.base_dn
)
260 self
.sd_utils
.dacl_add_ace("OU=test_computer_ou1," + self
.base_dn
, mod
)
262 computername
=self
.computernames
[0]
263 self
.add_computer_ldap(computername
)
265 res
= self
.admin_samdb
.search("%s" % self
.base_dn
,
266 expression
="(&(objectClass=computer)(samAccountName=%s$))" % computername
,
272 m
["description"]= ldb
.MessageElement(
273 ("A description"), ldb
.FLAG_MOD_REPLACE
,
279 m
["userAccountControl"] = ldb
.MessageElement(str(samba
.dsdb
.UF_WORKSTATION_TRUST_ACCOUNT|samba
.dsdb
.UF_PARTIAL_SECRETS_ACCOUNT
),
280 ldb
.FLAG_MOD_REPLACE
, "userAccountControl")
283 self
.fail("Unexpectedly able to set userAccountControl on %s" % m
.dn
)
284 except LdbError
, (enum
, estr
):
285 self
.assertEqual(ldb
.ERR_INSUFFICIENT_ACCESS_RIGHTS
, enum
)
289 m
["userAccountControl"] = ldb
.MessageElement(str(samba
.dsdb
.UF_SERVER_TRUST_ACCOUNT
),
290 ldb
.FLAG_MOD_REPLACE
, "userAccountControl")
294 except LdbError
, (enum
, estr
):
295 self
.assertEqual(ldb
.ERR_INSUFFICIENT_ACCESS_RIGHTS
, enum
)
299 m
["userAccountControl"] = ldb
.MessageElement(str(samba
.dsdb
.UF_NORMAL_ACCOUNT
),
300 ldb
.FLAG_MOD_REPLACE
, "userAccountControl")
305 m
["userAccountControl"] = ldb
.MessageElement(str(samba
.dsdb
.UF_WORKSTATION_TRUST_ACCOUNT
),
306 ldb
.FLAG_MOD_REPLACE
, "userAccountControl")
309 def test_admin_mod_uac(self
):
310 computername
=self
.computernames
[0]
311 self
.add_computer_ldap(computername
, samdb
=self
.admin_samdb
)
313 res
= self
.admin_samdb
.search("%s" % self
.base_dn
,
314 expression
="(&(objectClass=computer)(samAccountName=%s$))" % computername
,
316 attrs
=["userAccountControl"])
318 self
.assertEqual(int(res
[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT|UF_ACCOUNTDISABLE|UF_PASSWD_NOTREQD
)
322 m
["userAccountControl"] = ldb
.MessageElement(str(UF_WORKSTATION_TRUST_ACCOUNT|UF_PARTIAL_SECRETS_ACCOUNT|UF_TRUSTED_FOR_DELEGATION
),
323 ldb
.FLAG_MOD_REPLACE
, "userAccountControl")
325 self
.admin_samdb
.modify(m
)
326 self
.fail("Unexpectedly able to set userAccountControl to UF_WORKSTATION_TRUST_ACCOUNT|UF_PARTIAL_SECRETS_ACCOUNT|UF_TRUSTED_FOR_DELEGATION on %s" % m
.dn
)
327 except LdbError
, (enum
, estr
):
328 self
.assertEqual(ldb
.ERR_OTHER
, enum
)
332 m
["userAccountControl"] = ldb
.MessageElement(str(UF_WORKSTATION_TRUST_ACCOUNT|UF_PARTIAL_SECRETS_ACCOUNT
),
333 ldb
.FLAG_MOD_REPLACE
, "userAccountControl")
334 self
.admin_samdb
.modify(m
)
336 res
= self
.admin_samdb
.search("%s" % self
.base_dn
,
337 expression
="(&(objectClass=computer)(samAccountName=%s$))" % computername
,
339 attrs
=["userAccountControl"])
341 self
.assertEqual(int(res
[0]["userAccountControl"][0]), UF_WORKSTATION_TRUST_ACCOUNT|UF_PARTIAL_SECRETS_ACCOUNT
)
344 m
["userAccountControl"] = ldb
.MessageElement(str(UF_ACCOUNTDISABLE
),
345 ldb
.FLAG_MOD_REPLACE
, "userAccountControl")
346 self
.admin_samdb
.modify(m
)
348 res
= self
.admin_samdb
.search("%s" % self
.base_dn
,
349 expression
="(&(objectClass=computer)(samAccountName=%s$))" % computername
,
351 attrs
=["userAccountControl"])
353 self
.assertEqual(int(res
[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT| UF_ACCOUNTDISABLE
)
356 def test_uac_bits_set(self
):
357 user_sid
= self
.sd_utils
.get_object_sid(self
.unpriv_user_dn
)
358 mod
= "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid
)
360 old_sd
= self
.sd_utils
.read_sd_on_dn("OU=test_computer_ou1," + self
.base_dn
)
362 self
.sd_utils
.dacl_add_ace("OU=test_computer_ou1," + self
.base_dn
, mod
)
364 computername
=self
.computernames
[0]
365 self
.add_computer_ldap(computername
)
367 res
= self
.admin_samdb
.search("%s" % self
.base_dn
,
368 expression
="(&(objectClass=computer)(samAccountName=%s$))" % computername
,
374 m
["description"]= ldb
.MessageElement(
375 ("A description"), ldb
.FLAG_MOD_REPLACE
,
379 # These bits are privileged, but authenticated users have that CAR by default, so this is a pain to test
380 priv_to_auth_users_bits
= set([UF_PASSWD_NOTREQD
, UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED
,
381 UF_DONT_EXPIRE_PASSWD
])
383 # These bits really are privileged
384 priv_bits
= set([UF_INTERDOMAIN_TRUST_ACCOUNT
, UF_SERVER_TRUST_ACCOUNT
,
385 UF_TRUSTED_FOR_DELEGATION
, UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
])
387 invalid_bits
= set([UF_TEMP_DUPLICATE_ACCOUNT
, UF_PARTIAL_SECRETS_ACCOUNT
])
392 m
["userAccountControl"] = ldb
.MessageElement(str(bit|UF_PASSWD_NOTREQD
),
393 ldb
.FLAG_MOD_REPLACE
, "userAccountControl")
396 if (bit
in priv_bits
):
397 self
.fail("Unexpectedly able to set userAccountControl bit 0x%08X on %s" % (bit
, m
.dn
))
398 except LdbError
, (enum
, estr
):
399 if bit
in invalid_bits
:
400 self
.assertEqual(enum
, ldb
.ERR_OTHER
, "was not able to set 0x%08X on %s" % (bit
, m
.dn
))
401 # No point going on, try the next bit
403 elif (bit
in priv_bits
):
404 self
.assertEqual(ldb
.ERR_INSUFFICIENT_ACCESS_RIGHTS
, enum
)
406 self
.fail("Unable to set userAccountControl bit 0x%08X on %s: %s" % (bit
, m
.dn
, estr
))
409 def test_uac_bits_unrelated_modify(self
):
410 user_sid
= self
.sd_utils
.get_object_sid(self
.unpriv_user_dn
)
411 mod
= "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid
)
413 old_sd
= self
.sd_utils
.read_sd_on_dn("OU=test_computer_ou1," + self
.base_dn
)
415 self
.sd_utils
.dacl_add_ace("OU=test_computer_ou1," + self
.base_dn
, mod
)
417 computername
=self
.computernames
[0]
418 self
.add_computer_ldap(computername
)
420 res
= self
.admin_samdb
.search("%s" % self
.base_dn
,
421 expression
="(&(objectClass=computer)(samAccountName=%s$))" % computername
,
427 m
["description"]= ldb
.MessageElement(
428 ("A description"), ldb
.FLAG_MOD_REPLACE
,
432 invalid_bits
= set([UF_TEMP_DUPLICATE_ACCOUNT
, UF_PARTIAL_SECRETS_ACCOUNT
])
434 super_priv_bits
= set([UF_INTERDOMAIN_TRUST_ACCOUNT
])
436 priv_to_remove_bits
= set([UF_TRUSTED_FOR_DELEGATION
, UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
])
441 m
["userAccountControl"] = ldb
.MessageElement(str(bit|UF_PASSWD_NOTREQD
),
442 ldb
.FLAG_MOD_REPLACE
, "userAccountControl")
444 self
.admin_samdb
.modify(m
)
445 if bit
in invalid_bits
:
446 self
.fail("Should have been unable to set userAccountControl bit 0x%08X on %s" % (bit
, m
.dn
))
448 except LdbError
, (enum
, estr
):
449 if bit
in invalid_bits
:
450 self
.assertEqual(enum
, ldb
.ERR_OTHER
)
451 # No point going on, try the next bit
453 elif bit
in super_priv_bits
:
454 self
.assertEqual(enum
, ldb
.ERR_INSUFFICIENT_ACCESS_RIGHTS
)
455 # No point going on, try the next bit
458 self
.fail("Unable to set userAccountControl bit 0x%08X on %s: %s" % (bit
, m
.dn
, estr
))
463 m
["userAccountControl"] = ldb
.MessageElement(str(bit|UF_PASSWD_NOTREQD|UF_ACCOUNTDISABLE
),
464 ldb
.FLAG_MOD_REPLACE
, "userAccountControl")
467 except LdbError
, (enum
, estr
):
468 self
.fail("Unable to set userAccountControl bit 0x%08X on %s: %s" % (bit
, m
.dn
, estr
))
473 m
["userAccountControl"] = ldb
.MessageElement(str(UF_PASSWD_NOTREQD|UF_ACCOUNTDISABLE
),
474 ldb
.FLAG_MOD_REPLACE
, "userAccountControl")
476 if bit
in priv_to_remove_bits
:
477 self
.fail("Should have been unable to remove userAccountControl bit 0x%08X on %s" % (bit
, m
.dn
))
479 except LdbError
, (enum
, estr
):
480 if bit
in priv_to_remove_bits
:
481 self
.assertEqual(enum
, ldb
.ERR_INSUFFICIENT_ACCESS_RIGHTS
)
483 self
.fail("Unexpectedly able to remove userAccountControl bit 0x%08X on %s: %s" % (bit
, m
.dn
, estr
))
485 def test_uac_bits_add(self
):
486 computername
=self
.computernames
[0]
488 user_sid
= self
.sd_utils
.get_object_sid(self
.unpriv_user_dn
)
489 mod
= "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid
)
491 old_sd
= self
.sd_utils
.read_sd_on_dn("OU=test_computer_ou1," + self
.base_dn
)
493 self
.sd_utils
.dacl_add_ace("OU=test_computer_ou1," + self
.base_dn
, mod
)
495 invalid_bits
= set([UF_TEMP_DUPLICATE_ACCOUNT
, UF_PARTIAL_SECRETS_ACCOUNT
])
497 # These bits are privileged, but authenticated users have that CAR by default, so this is a pain to test
498 priv_to_auth_users_bits
= set([UF_PASSWD_NOTREQD
, UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED
,
499 UF_DONT_EXPIRE_PASSWD
])
501 # These bits really are privileged
502 priv_bits
= set([UF_INTERDOMAIN_TRUST_ACCOUNT
, UF_SERVER_TRUST_ACCOUNT
,
503 UF_TRUSTED_FOR_DELEGATION
, UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
])
507 self
.add_computer_ldap(computername
, others
={"userAccountControl": [str(bit
)]})
508 delete_force(self
.admin_samdb
, "CN=%s,OU=test_computer_ou1,%s" % (computername
, self
.base_dn
))
510 self
.fail("Unexpectdly able to set userAccountControl bit 0x%08X on %s" % (bit
, computername
))
512 except LdbError
, (enum
, estr
):
513 if bit
in invalid_bits
:
514 self
.assertEqual(enum
, ldb
.ERR_OTHER
, "Invalid bit 0x%08X was able to be set on %s" % (bit
, computername
))
515 # No point going on, try the next bit
517 elif bit
in priv_bits
:
518 self
.assertEqual(enum
, ldb
.ERR_INSUFFICIENT_ACCESS_RIGHTS
)
521 self
.fail("Unable to set userAccountControl bit 0x%08X on %s: %s" % (bit
, computername
, estr
))
525 runner
= SubunitTestRunner()
527 if not runner
.run(unittest
.makeSuite(UserAccountControlTests
)).wasSuccessful():