def run(self, name, user, H=None, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) sam = SamDB(H, session_info=system_session(), credentials=creds, lp=lp) res = sam.search( expression="servicePrincipalName=%s" % ldb.binary_encode(name), scope=ldb.SCOPE_SUBTREE) if len(res) != 0: raise CommandError("Service principal %s already" " affected to another user" % name) (cleaneduser, realm, domain) = _get_user_realm_domain(user) res = sam.search( expression="samaccountname=%s" % ldb.binary_encode(cleaneduser), scope=ldb.SCOPE_SUBTREE, attrs=["servicePrincipalName"]) if len(res) > 0: res[0].dn msg = ldb.Message() spns = res[0].get("servicePrincipalName") tab = [] found = False flag = ldb.FLAG_MOD_ADD if spns is not None: for e in spns: if str(e) == name: found = True tab.append(str(e)) flag = ldb.FLAG_MOD_REPLACE tab.append(name) msg.dn = res[0].dn msg["servicePrincipalName"] = ldb.MessageElement(tab, flag, "servicePrincipalName") if not found: sam.modify(msg) else: raise CommandError("Service principal %s already" " affected to %s" % (name, user)) else: raise CommandError("User %s not found" % user)
def seize_dns_role(self, role, samdb, credopts, sambaopts, versionopts, force): """Seize DNS FSMO role. """ serviceName = samdb.get_dsServiceName() domain_dn = samdb.domain_dn() forest_dn = samba.dn_from_dns_name(samdb.forest_dns_name()) self.domaindns_dn = "CN=Infrastructure,DC=DomainDnsZones," + domain_dn self.forestdns_dn = "CN=Infrastructure,DC=ForestDnsZones," + forest_dn m = ldb.Message() if role == "domaindns": m.dn = ldb.Dn(samdb, self.domaindns_dn) elif role == "forestdns": m.dn = ldb.Dn(samdb, self.forestdns_dn) else: raise CommandError("Invalid FSMO role.") #first try to transfer to avoid problem if the owner is still active seize = False master_owner = get_fsmo_roleowner(samdb, m.dn) if master_owner != serviceName: if force is None: self.message("Attempting transfer...") if not transfer_dns_role(self.outf, sambaopts, credopts, role, samdb): #transfer failed, use the big axe... seize = True self.message("Transfer unsuccessful, seizing...") else: self.message( "Not seizing role as transfer was successful\n") if force is not None or seize == True: self.message("Seizing %s FSMO role..." % role) m["fSMORoleOwner"] = ldb.MessageElement( serviceName, ldb.FLAG_MOD_REPLACE, "fSMORoleOwner") try: samdb.modify(m) except LdbError, (num, msg): raise CommandError("Failed to seize '%s' role: %s" % (role, msg)) self.outf.write("FSMO seize of '%s' role successful\n" % role) return True
def save_uptodate_vectors(self, samdb, partitions): """Ensures the UTDV used by DRS is correct after an offline backup""" for nc in partitions: # load the replUpToDateVector we *should* have utdv = _dsdb_load_udv_v2(samdb, nc) # convert it to NDR format and write it into the DB utdv_blob = drsblobs.replUpToDateVectorBlob() utdv_blob.version = 2 utdv_blob.ctr.cursors = utdv utdv_blob.ctr.count = len(utdv) new_value = ndr_pack(utdv_blob) m = ldb.Message() m.dn = ldb.Dn(samdb, nc) m["replUpToDateVector"] = ldb.MessageElement(new_value, ldb.FLAG_MOD_REPLACE, "replUpToDateVector") samdb.modify(m)
def test_modify_replace_text(self): l = ldb.Ldb(filename()) m = ldb.Message() m.dn = ldb.Dn(l, "dc=modify2") m.text["bla"] = ["1234", "456"] l.add(m) try: m = ldb.Message() m.dn = ldb.Dn(l, "dc=modify2") m["bla"] = ldb.MessageElement(["789"], ldb.FLAG_MOD_REPLACE, "bla") self.assertEqual(ldb.FLAG_MOD_REPLACE, m["bla"].flags()) l.modify(m) rm = l.search(m.dn)[0] self.assertEqual(2, len(rm)) self.assertEqual(["789"], list(rm.text["bla"])) rm = l.search(m.dn, attrs=["bla"])[0] self.assertEqual(1, len(rm)) finally: l.delete(ldb.Dn(l, "dc=modify2"))
def test_error_replpropertymetadata(self): res = self.samdb.search(expression="cn=Administrator", scope=ldb.SCOPE_SUBTREE, attrs=["replPropertyMetaData"]) repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob, str(res[0]["replPropertyMetaData"])) ctr = repl.ctr for o in ctr.array: # Search for Description if o.attid == 13: old_version = o.version o.version = o.version + 1 replBlob = ndr_pack(repl) msg = ldb.Message() msg.dn = res[0].dn msg["replPropertyMetaData"] = ldb.MessageElement( replBlob, ldb.FLAG_MOD_REPLACE, "replPropertyMetaData") self.assertRaises(ldb.LdbError, self.samdb.modify, msg, ["local_oid:1.3.6.1.4.1.7165.4.3.14:0"])
def update_machine_account_password(samdb, secrets_ldb, names): """Update (change) the password of the current DC both in the SAM db and in secret one :param samdb: An LDB object related to the sam.ldb file of a given provision :param secrets_ldb: An LDB object related to the secrets.ldb file of a given provision :param names: List of key provision parameters""" expression = "samAccountName=%s$" % names.netbiosname secrets_msg = secrets_ldb.search(expression=expression, attrs=["secureChannelType"]) if int(secrets_msg[0]["secureChannelType"][0]) == SEC_CHAN_BDC: res = samdb.search(expression=expression, attrs=[]) assert (len(res) == 1) msg = ldb.Message(res[0].dn) machinepass = samba.generate_random_machine_password(128, 255) mputf16 = machinepass.encode('utf-16-le') msg["clearTextPassword"] = ldb.MessageElement(mputf16, ldb.FLAG_MOD_REPLACE, "clearTextPassword") samdb.modify(msg) res = samdb.search(expression=("samAccountName=%s$" % names.netbiosname), attrs=["msDs-keyVersionNumber"]) assert (len(res) == 1) kvno = int(str(res[0]["msDs-keyVersionNumber"])) secChanType = int(secrets_msg[0]["secureChannelType"][0]) secretsdb_self_join(secrets_ldb, domain=names.domain, realm=names.realm, domainsid=names.domainsid, dnsdomain=names.dnsdomain, netbiosname=names.netbiosname, machinepass=machinepass, key_version_number=kvno, secure_channel_type=secChanType) else: raise ProvisioningError("Unable to find a Secure Channel" "of type SEC_CHAN_BDC")
def increment_xid(self): """Increment xidNumber, if not present it create and assign it to the lowerBound :return xid can that be used for SID/unixid mapping """ res = self.search(expression="distinguishedName=CN=CONFIG", base="", scope=ldb.SCOPE_SUBTREE) id = res[0].get("xidNumber") flag = ldb.FLAG_MOD_REPLACE if id is None: id = res[0].get("lowerBound") flag = ldb.FLAG_MOD_ADD newid = int(str(id)) + 1 msg = ldb.Message() msg.dn = ldb.Dn(self, "CN=CONFIG") msg["xidNumber"] = ldb.MessageElement(str(newid), flag, "xidNumber") self.modify(msg) return id
def err_empty_attribute(self, dn, attrname): '''fix empty attributes''' self.report("ERROR: Empty attribute %s in %s" % (attrname, dn)) if not self.confirm('Remove empty attribute %s from %s?' % (attrname, dn)): self.report("Not fixing empty attribute %s" % attrname) return m = ldb.Message() m.dn = dn m[attrname] = ldb.MessageElement('', ldb.FLAG_MOD_DELETE, attrname) if self.verbose: self.report(self.samdb.write_ldif(m, ldb.CHANGETYPE_MODIFY)) try: self.samdb.modify(m, controls=["relax:0"], validate=False) except Exception, msg: self.report("Failed to remove empty attribute %s : %s" % (attrname, msg)) return
def err_wrong_sd(self, dn, sd, sd_broken): '''re-write replPropertyMetaData elements for a single attribute for a object. This is used to fix missing replPropertyMetaData elements''' sd_attr = "nTSecurityDescriptor" sd_val = ndr_pack(sd) sd_flags = security.SECINFO_DACL | security.SECINFO_SACL if not self.confirm_all('Fix %s on %s?' % (sd_attr, dn), 'fix_ntsecuritydescriptor'): self.report('Not fixing %s on %s\n' % (sd_attr, dn)) return nmsg = ldb.Message() nmsg.dn = dn nmsg[sd_attr] = ldb.MessageElement(sd_val, ldb.FLAG_MOD_REPLACE, sd_attr) if self.do_modify(nmsg, ["sd_flags:1:%d" % sd_flags], "Failed to fix metadata for attribute %s" % sd_attr): self.report("Fixed attribute '%s' of '%s'\n" % (sd_attr, dn))
def _test_ldap_change_password_reveal_on_demand(self, errno=None): self.zero_min_password_age() res = self.rodc_db.search(self.rodc_dn, scope=ldb.SCOPE_BASE, attrs=['msDS-RevealOnDemandGroup']) group = res[0]['msDS-RevealOnDemandGroup'][0] user_dn, username, password = self._new_user() creds1 = make_creds(username, password) m = ldb.Message() m.dn = ldb.Dn(self.rwdc_db, group) m['member'] = ldb.MessageElement(user_dn, ldb.FLAG_MOD_ADD, 'member') self.rwdc_db.modify(m) # Against Windows, this will just forward if no account exists on the KDC # Therefore, this does not error on Windows. self.try_ldap_logon(RODC, creds1, ldb.ERR_INVALID_CREDENTIALS) self.force_replication() # The proxy case self.try_ldap_logon(RODC, creds1) preload_rodc_user(user_dn) # Now the user AND password are replicated to RODC, so logon should work (not proxy case) self.try_ldap_logon(RODC, creds1) passwords = ['password#%s' % i for i in range(1, 6)] for prev, password in zip(passwords[:-1], passwords[1:]): self._change_password(user_dn, prev, password) # The password has changed enough times to make the old # password invalid, but the RODC shouldn't know that. self.try_ldap_logon(RODC, creds1) self.try_ldap_logon(RWDC, creds1, errno) creds2 = make_creds(username, password) self.try_ldap_logon(RWDC, creds2) self.try_ldap_logon(RODC, creds2, errno)
def run(self, attribute, H=None, credopts=None, sambaopts=None, versionopts=None, searchflags=None): if searchflags is None: raise CommandError('A value to modify must be provided.') # Parse the search flags to a set of bits to modify. searchflags_int = None if searchflags is not None: searchflags_int = 0 flags = searchflags.split(',') # We have to normalise all the values. To achieve this predictably # we title case (Fattrindex), then swapcase (fATTINDEX) flags = [ x.capitalize().swapcase() for x in flags ] for flag in flags: if flag not in bitFields['searchflags'].keys(): raise CommandError("Unknown flag '%s', please see --help" % flag) bit_loc = 31 - bitFields['searchflags'][flag] # Now apply the bit. searchflags_int = searchflags_int | (1 << bit_loc) lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) schema_dn = samdb.schema_dn() # For now we make assumptions about the CN attr_dn = 'cn=%s,%s' % (attribute, schema_dn) m = ldb.Message() m.dn = ldb.Dn(samdb, attr_dn) if searchflags_int is not None: m['searchFlags'] = ldb.MessageElement( str(searchflags_int), ldb.FLAG_MOD_REPLACE, 'searchFlags') samdb.modify(m) samdb.set_schema_update_now() self.outf.write("modified %s" % attr_dn)
def test_set_replpropertymetadata(self): res = self.samdb.search(scope=ldb.SCOPE_SUBTREE, base=self.account_dn, attrs=["replPropertyMetaData", "uSNChanged"]) repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob, res[0]["replPropertyMetaData"][0]) ctr = repl.ctr for o in ctr.array: # Search for Description if o.attid == 13: old_version = o.version o.version = o.version + 1 o.local_usn = int(str(res[0]["uSNChanged"])) + 1 o.originating_usn = int(str(res[0]["uSNChanged"])) + 1 replBlob = ndr_pack(repl) msg = ldb.Message() msg.dn = res[0].dn msg["replPropertyMetaData"] = ldb.MessageElement( replBlob, ldb.FLAG_MOD_REPLACE, "replPropertyMetaData") self.samdb.modify(msg, ["local_oid:1.3.6.1.4.1.7165.4.3.14:0"])
def test_admin_mod_uac(self): computername=self.computernames[0] self.add_computer_ldap(computername, samdb=self.admin_samdb) res = self.admin_samdb.search("%s" % self.base_dn, expression="(&(objectClass=computer)(samAccountName=%s$))" % computername, scope=SCOPE_SUBTREE, attrs=["userAccountControl"]) self.assertEqual(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT|UF_ACCOUNTDISABLE|UF_PASSWD_NOTREQD) m = ldb.Message() m.dn = res[0].dn m["userAccountControl"] = ldb.MessageElement(str(UF_WORKSTATION_TRUST_ACCOUNT|UF_PARTIAL_SECRETS_ACCOUNT|UF_TRUSTED_FOR_DELEGATION), ldb.FLAG_MOD_REPLACE, "userAccountControl") try: self.admin_samdb.modify(m) self.fail("Unexpectedly able to set userAccountControl to UF_WORKSTATION_TRUST_ACCOUNT|UF_PARTIAL_SECRETS_ACCOUNT|UF_TRUSTED_FOR_DELEGATION on %s" % m.dn) except LdbError, (enum, estr): self.assertEqual(ldb.ERR_OTHER, enum)
def test_modify_delete(self): l = ldb.Ldb(filename()) m = ldb.Message() m.dn = ldb.Dn(l, "dc=modifydelete") m["bla"] = ["1234"] l.add(m) rm = l.search(m.dn)[0] self.assertEquals(["1234"], list(rm["bla"])) try: m = ldb.Message() m.dn = ldb.Dn(l, "dc=modifydelete") m["bla"] = ldb.MessageElement([], ldb.FLAG_MOD_DELETE, "bla") self.assertEquals(ldb.FLAG_MOD_DELETE, m["bla"].flags()) l.modify(m) rm = l.search(m.dn)[0] self.assertEquals(1, len(rm)) rm = l.search(m.dn, attrs=["bla"])[0] self.assertEquals(0, len(rm)) finally: l.delete(ldb.Dn(l, "dc=modifydelete"))
def join_finalise(ctx): '''finalise the join, mark us synchronised and setup secrets db''' print "Setting isSynchronized" m = ldb.Message() m.dn = ldb.Dn(ctx.samdb, '@ROOTDSE') m["isSynchronized"] = ldb.MessageElement("TRUE", ldb.FLAG_MOD_REPLACE, "isSynchronized") ctx.samdb.modify(m) secrets_ldb = Ldb(ctx.paths.secrets, session_info=system_session(), lp=ctx.lp) print "Setting up secrets database" secretsdb_self_join(secrets_ldb, domain=ctx.domain_name, realm=ctx.realm, dnsdomain=ctx.dnsdomain, netbiosname=ctx.myname, domainsid=security.dom_sid(ctx.domsid), machinepass=ctx.acct_pass, secure_channel_type=ctx.secure_channel_type, key_version_number=ctx.key_version_number)
def add_dns_container(samdb, domaindn, prefix, domain_sid, dnsadmins_sid, forest=False): name_map = {'DnsAdmins': str(dnsadmins_sid)} if forest is True: sd_val = get_dns_forest_microsoft_dns_descriptor(domain_sid, name_map=name_map) else: sd_val = get_dns_domain_microsoft_dns_descriptor(domain_sid, name_map=name_map) # CN=MicrosoftDNS,<PREFIX>,<DOMAINDN> msg = ldb.Message( ldb.Dn(samdb, "CN=MicrosoftDNS,%s,%s" % (prefix, domaindn))) msg["objectClass"] = ["top", "container"] msg["nTSecurityDescriptor"] = ldb.MessageElement(sd_val, ldb.FLAG_MOD_ADD, "nTSecurityDescriptor") samdb.add(msg)
def updateOEMInfo(samdb, rootdn): """Update the OEMinfo field to add information about upgrade :param samdb: an LDB object connected to the sam DB :param rootdn: The string representation of the root DN of the provision (ie. DC=...,DC=...) """ res = samdb.search(expression="(objectClass=*)", base=rootdn, scope=SCOPE_BASE, attrs=["dn", "oEMInformation"]) if len(res) > 0: if res[0].get("oEMInformation"): info = str(res[0]["oEMInformation"]) else: info = "" info = "%s, upgrade to %s" % (info, version) delta = ldb.Message() delta.dn = ldb.Dn(samdb, str(res[0]["dn"])) delta["oEMInformation"] = ldb.MessageElement(info, ldb.FLAG_MOD_REPLACE, "oEMInformation" ) samdb.modify(delta)
def run(self, accountname, principal, H=None, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) paths = provision.provision_paths_from_lp(lp, lp.get("realm")) if H == None: path = paths.samdb else: path = H sam = SamDB(path, session_info=system_session(), credentials=creds, lp=lp) # TODO once I understand how, use the domain info to naildown # to the correct domain (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname) res = sam.search(expression="sAMAccountName=%s" % ldb.binary_encode(cleanedaccount), scope=ldb.SCOPE_SUBTREE, attrs=["msDS-AllowedToDelegateTo"]) if len(res) == 0: raise CommandError("Unable to find account name '%s'" % accountname) assert (len(res) == 1) msg = ldb.Message() msg.dn = res[0].dn msg["msDS-AllowedToDelegateTo"] = ldb.MessageElement( [principal], ldb.FLAG_MOD_DELETE, "msDS-AllowedToDelegateTo") try: sam.modify(msg) except Exception, err: raise CommandError(err)
def run(self, psoname, user_or_group, H=None, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) pso_dn = "CN=%s,%s" % (psoname, pso_container(samdb)) # sanity-check the PSO exists check_pso_valid(samdb, pso_dn, psoname) # lookup the user/group by account-name to gets its DN search_filter = "(sAMAccountName=%s)" % user_or_group res = samdb.search(samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE, expression=search_filter) if len(res) == 0: raise CommandError("The specified user or group '%s' was not found" % user_or_group) # modify the PSO to apply to the user/group specified target_dn = str(res[0].dn) m = ldb.Message() m.dn = ldb.Dn(samdb, pso_dn) m["msDS-PSOAppliesTo"] = ldb.MessageElement(target_dn, ldb.FLAG_MOD_DELETE, "msDS-PSOAppliesTo") try: samdb.modify(m) except ldb.LdbError as e: (num, msg) = e.args # most likely error - PSO doesn't apply to that user/group if num == ldb.ERR_NO_SUCH_ATTRIBUTE: raise CommandError("PSO '%s' doesn't apply to '%s'" % (psoname, user_or_group)) else: raise CommandError("Failed to update PSO '%s': %s" % (psoname, msg)) self.message("PSO '%s' no longer applies to '%s'" % (psoname, user_or_group))
def add_users_to_group(samdb, group, members, logger): """Add user/member to group/alias param samdb: Samba4 SAM database param group: Groupmap object param members: List of member SIDs param logger: Logger object """ for member_sid in members: m = ldb.Message() m.dn = ldb.Dn(samdb, "<SID=%s>" % str(group.sid)) m['a01'] = ldb.MessageElement("<SID=%s>" % str(member_sid), ldb.FLAG_MOD_ADD, 'member') try: samdb.modify(m) except ldb.LdbError, (ecode, emsg): if ecode == ldb.ERR_ENTRY_ALREADY_EXISTS: logger.debug("skipped re-adding member '%s' to group '%s': %s", member_sid, group.sid, emsg) elif ecode == ldb.ERR_NO_SUCH_OBJECT: raise ProvisioningError("Could not add member '%s' to group '%s' as either group or user record doesn't exist: %s" % (member_sid, group.sid, emsg)) else: raise ProvisioningError("Could not add member '%s' to group '%s': %s" % (member_sid, group.sid, emsg))
def run(self, DC=None, dsa_option=None, sambaopts=None, credopts=None, versionopts=None): self.lp = sambaopts.get_loadparm() if DC is None: DC = common.netcmd_dnsname(self.lp) self.server = DC self.creds = credopts.get_credentials(self.lp, fallback_machine=True) samdb_connect(self) ntds_dn = self.samdb.get_dsServiceName() res = self.samdb.search(base=ntds_dn, scope=ldb.SCOPE_BASE, attrs=["options"]) dsa_opts = int(res[0]["options"][0]) # print out current DSA options cur_opts = [x for x in self.option_map if self.option_map[x] & dsa_opts] self.message("Current DSA options: " + ", ".join(cur_opts)) # modify options if dsa_option: if dsa_option[:1] not in ("+", "-"): raise CommandError("Unknown option %s" % dsa_option) flag = dsa_option[1:] if flag not in self.option_map.keys(): raise CommandError("Unknown option %s" % dsa_option) if dsa_option[:1] == "+": dsa_opts |= self.option_map[flag] else: dsa_opts &= ~self.option_map[flag] #save new options m = ldb.Message() m.dn = ldb.Dn(self.samdb, ntds_dn) m["options"]= ldb.MessageElement(str(dsa_opts), ldb.FLAG_MOD_REPLACE, "options") self.samdb.modify(m) # print out new DSA options cur_opts = [x for x in self.option_map if self.option_map[x] & dsa_opts] self.message("New DSA options: " + ", ".join(cur_opts))
def test_modify_delete_text(self): l = ldb.Ldb(filename()) m = ldb.Message() m.dn = ldb.Dn(l, "dc=modifydelete") m.text["bla"] = ["1234"] l.add(m) rm = l.search(m.dn)[0] self.assertEqual(["1234"], list(rm.text["bla"])) try: m = ldb.Message() m.dn = ldb.Dn(l, "dc=modifydelete") m["bla"] = ldb.MessageElement([], ldb.FLAG_MOD_DELETE, "bla") self.assertEqual(ldb.FLAG_MOD_DELETE, m["bla"].flags()) l.modify(m) rm = l.search(m.dn) self.assertEqual(1, len(rm)) self.assertEqual(set(["dn", "distinguishedName"]), set(rm[0].keys())) rm = l.search(m.dn, attrs=["bla"]) self.assertEqual(1, len(rm)) self.assertEqual(0, len(rm[0])) finally: l.delete(ldb.Dn(l, "dc=modifydelete"))
def check_rootdse(self): '''check the @ROOTDSE special object''' dn = ldb.Dn(self.samdb, '@ROOTDSE') if self.verbose: self.report("Checking object %s" % dn) res = self.samdb.search(base=dn, scope=ldb.SCOPE_BASE) if len(res) != 1: self.report("Object %s disappeared during check" % dn) return 1 obj = res[0] error_count = 0 # check that the dsServiceName is in GUID form if not 'dsServiceName' in obj: self.report('ERROR: dsServiceName missing in @ROOTDSE') return error_count + 1 if not obj['dsServiceName'][0].startswith('<GUID='): self.report('ERROR: dsServiceName not in GUID form in @ROOTDSE') error_count += 1 if not self.confirm('Change dsServiceName to GUID form?'): return error_count res = self.samdb.search(base=ldb.Dn(self.samdb, obj['dsServiceName'][0]), scope=ldb.SCOPE_BASE, attrs=['objectGUID']) guid_str = str(ndr_unpack(misc.GUID, res[0]['objectGUID'][0])) m = ldb.Message() m.dn = dn m['dsServiceName'] = ldb.MessageElement("<GUID=%s>" % guid_str, ldb.FLAG_MOD_REPLACE, 'dsServiceName') if self.do_modify(m, [], "Failed to change dsServiceName to GUID form", validate=False): self.report("Changed dsServiceName to GUID form") return error_count
def test_edit_rid_master(self): """Test doing a RID allocation after changing the RID master from the original one. This should set rIDNextRID to 0 on the new RID master.""" # 1. a. Transfer role to non-RID master # b. Check that it succeeds correctly # # 2. a. Call the RID alloc against the former master. # b. Check that it succeeds. fsmo_dn = ldb.Dn( self.ldb_dc1, "CN=RID Manager$,CN=System," + self.ldb_dc1.domain_dn()) (fsmo_owner, fsmo_not_owner) = self._determine_fSMORoleOwner(fsmo_dn) # 1. Swap RID master role m = ldb.Message() m.dn = ldb.Dn(self.ldb_dc1, "") m["becomeRidMaster"] = ldb.MessageElement("1", ldb.FLAG_MOD_REPLACE, "becomeRidMaster") # Make sure that ldb_dc1 == RID Master server_dn = str( ldb.Dn(self.ldb_dc1, self.ldb_dc1.get_dsServiceName()).parent()) # self.ldb_dc1 == LOCALDC if server_dn == fsmo_owner['server_dn']: # ldb_dc1 == VAMPIREDC ldb_dc1, ldb_dc2 = self.ldb_dc2, self.ldb_dc1 else: # Otherwise switch the two ldb_dc1, ldb_dc2 = self.ldb_dc1, self.ldb_dc2 try: # ldb_dc1 is now RID MASTER (as VAMPIREDC) ldb_dc1.modify(m) except ldb.LdbError, (num, msg): self.fail("Failed to reassign RID Master " + msg)
def add_krbtgt_account(ctx): '''RODCs need a special krbtgt account''' print "Adding %s" % ctx.krbtgt_dn rec = { "dn": ctx.krbtgt_dn, "objectclass": "user", "useraccountcontrol": str(samba.dsdb.UF_NORMAL_ACCOUNT | samba.dsdb.UF_ACCOUNTDISABLE), "showinadvancedviewonly": "TRUE", "description": "krbtgt for %s" % ctx.samname } ctx.samdb.add(rec, ["rodc_join:1:1"]) # now we need to search for the samAccountName attribute on the krbtgt DN, # as this will have been magically set to the krbtgt number res = ctx.samdb.search(base=ctx.krbtgt_dn, scope=ldb.SCOPE_BASE, attrs=["samAccountName"]) ctx.krbtgt_name = res[0]["samAccountName"][0] print "Got krbtgt_name=%s" % ctx.krbtgt_name m = ldb.Message() m.dn = ldb.Dn(ctx.samdb, ctx.acct_dn) m["msDS-krbTgtLink"] = ldb.MessageElement(ctx.krbtgt_dn, ldb.FLAG_MOD_REPLACE, "msDS-krbTgtLink") ctx.samdb.modify(m) ctx.new_krbtgt_dn = "CN=%s,CN=Users,%s" % (ctx.krbtgt_name, ctx.base_dn) print "Renaming %s to %s" % (ctx.krbtgt_dn, ctx.new_krbtgt_dn) ctx.samdb.rename(ctx.krbtgt_dn, ctx.new_krbtgt_dn)
def post_setup(self): ldapi_db = Ldb(self.ldapi_uri, credentials=self.credentials) # delete default SASL mappings res = ldapi_db.search(expression="(!(cn=samba-admin mapping))", base="cn=mapping,cn=sasl,cn=config", scope=SCOPE_ONELEVEL, attrs=["dn"]) # configure in-directory access control on Fedora DS via the aci attribute (over a direct ldapi:// socket) for i in range (0, len(res)): dn = str(res[i]["dn"]) ldapi_db.delete(dn) aci = """(targetattr = "*") (version 3.0;acl "full access to all by samba-admin";allow (all)(userdn = "ldap:///CN=samba-admin,%s");)""" % self.sambadn m = ldb.Message() m["aci"] = ldb.MessageElement([aci], ldb.FLAG_MOD_REPLACE, "aci") m.dn = ldb.Dn(1, self.names.domaindn) ldapi_db.modify(m) m.dn = ldb.Dn(1, self.names.configdn) ldapi_db.modify(m) m.dn = ldb.Dn(1, self.names.schemadn) ldapi_db.modify(m)
def _test_modify_replicated_attributes(self): dn = 'CN=Guest,CN=Users,' + self.base_dn value = self.tag for attr in ['carLicense', 'middleName']: m = ldb.Message() m.dn = ldb.Dn(self.rwdc_db, dn) m[attr] = ldb.MessageElement(value, ldb.FLAG_MOD_REPLACE, attr) try: self.rwdc_db.modify(m) except ldb.LdbError as e: self.fail("Failed to modify %s %s on RWDC %s with %s" % (dn, attr, RWDC, e)) self.force_replication() try: res = self.rodc_db.search(dn, scope=ldb.SCOPE_SUBTREE, attrs=[attr]) results = [x[attr][0] for x in res] self.assertEqual(results, [value]) except ldb.LdbError, e: self.assertNotEqual(e.args[0], ldb.ERR_NO_SUCH_OBJECT, "replication seems to have failed")
def _get_mock_rodc_creds(self, spns): rodc_ctx = self.get_mock_rodc_ctx() for spn in spns: spn = spn.format(account=rodc_ctx.myname) if spn not in rodc_ctx.SPNs: rodc_ctx.SPNs.append(spn) samdb = self.get_samdb() rodc_dn = ldb.Dn(samdb, rodc_ctx.acct_dn) msg = ldb.Message(rodc_dn) msg['servicePrincipalName'] = ldb.MessageElement( rodc_ctx.SPNs, ldb.FLAG_MOD_REPLACE, 'servicePrincipalName') samdb.modify(msg) creds = KerberosCredentials() creds.guess(self.get_lp()) creds.set_realm(rodc_ctx.realm.upper()) creds.set_domain(rodc_ctx.domain_name) creds.set_password(rodc_ctx.acct_pass) creds.set_username(rodc_ctx.myname) creds.set_workstation(rodc_ctx.samname) creds.set_dn(rodc_dn) creds.set_spn(rodc_ctx.SPNs) res = samdb.search(base=rodc_dn, scope=ldb.SCOPE_BASE, attrs=['msDS-KeyVersionNumber']) kvno = int(res[0].get('msDS-KeyVersionNumber', idx=0)) creds.set_kvno(kvno) keys = self.get_keys(samdb, rodc_dn) self.creds_set_keys(creds, keys) return creds
def test_modify_replicated_attributes(self): # some timestamp ones dn = 'CN=Guest,CN=Users,' + self.base_dn value = 'hallooo' for attr in ['carLicense', 'middleName']: msg = ldb.Message() msg.dn = ldb.Dn(self.samdb, dn) msg[attr] = ldb.MessageElement(value, ldb.FLAG_MOD_REPLACE, attr) try: self.samdb.modify(msg) self.fail("Failed to fail to modify %s %s" % (dn, attr)) except ldb.LdbError as e1: (ecode, emsg) = e1.args if ecode != ldb.ERR_REFERRAL: self.fail("Failed to REFER when trying to modify %s %s" % (dn, attr)) else: m = re.search(r'(ldap://[^>]+)>', emsg) if m is None: self.fail("referral seems not to refer to anything") address = m.group(1) try: tmpdb = SamDB(address, credentials=CREDS, session_info=system_session(LP), lp=LP) tmpdb.modify(msg) except ldb.LdbError as e: self.fail("couldn't modify referred location %s" % address) if address.lower().startswith( self.samdb.domain_dns_name()): self.fail( "referral address did not give a specific DC")
def remove_linked_attribute(self, src, dest, attr='member'): m = ldb.Message() m.dn = ldb.Dn(self.ldb_dc1, src) m[attr] = ldb.MessageElement(dest, ldb.FLAG_MOD_DELETE, attr) self.ldb_dc1.modify(m)