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 import_idmap(idmapdb, samba3, logger): """Import idmap data. :param idmapdb: Samba4 IDMAP database :param samba3_idmap: Samba3 IDMAP database to import from :param logger: Logger object """ try: samba3_idmap = samba3.get_idmap_db() except IOError as e: logger.warn('Cannot open idmap database, Ignoring: %s', str(e)) return currentxid = max(samba3_idmap.get_user_hwm(), samba3_idmap.get_group_hwm()) lowerbound = currentxid # FIXME: upperbound m = ldb.Message() m.dn = ldb.Dn(idmapdb, 'CN=CONFIG') m['lowerbound'] = ldb.MessageElement(str(lowerbound), ldb.FLAG_MOD_REPLACE, 'lowerBound') m['xidNumber'] = ldb.MessageElement(str(currentxid), ldb.FLAG_MOD_REPLACE, 'xidNumber') idmapdb.modify(m) for id_type, xid in samba3_idmap.ids(): if id_type == 'UID': xid_type = 'ID_TYPE_UID' elif id_type == 'GID': xid_type = 'ID_TYPE_GID' else: logger.warn('Wrong type of entry in idmap (%s), Ignoring', id_type) continue sid = samba3_idmap.get_sid(xid, id_type) add_idmap_entry(idmapdb, dom_sid(sid), xid, xid_type, logger)
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 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 err_normalise_mismatch(self, dn, attrname, values): '''fix attribute normalisation errors''' self.report("ERROR: Normalisation error for attribute %s in %s" % (attrname, dn)) mod_list = [] for val in values: normalised = self.samdb.dsdb_normalise_attributes( self.samdb_schema, attrname, [val]) if len(normalised) != 1: self.report("Unable to normalise value '%s'" % val) mod_list.append((val, '')) elif (normalised[0] != val): self.report("value '%s' should be '%s'" % (val, normalised[0])) mod_list.append((val, normalised[0])) if not self.confirm('Fix normalisation for %s from %s?' % (attrname, dn)): self.report("Not fixing attribute %s" % attrname) return m = ldb.Message() m.dn = dn for i in range(0, len(mod_list)): (val, nval) = mod_list[i] m['value_%u' % i] = ldb.MessageElement(val, ldb.FLAG_MOD_DELETE, attrname) if nval != '': m['normv_%u' % i] = ldb.MessageElement(nval, ldb.FLAG_MOD_ADD, 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 normalise attribute %s : %s" % (attrname, msg)) return
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 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 update_dns_root(self, logger, samdb, old_realm, delete_old_dns): '''Updates dnsRoot for the partition objects to reflect the rename''' # lookup the crossRef objects that hold the old realm's dnsRoot partitions_dn = samdb.get_partitions_dn() res = samdb.search(base=partitions_dn, scope=ldb.SCOPE_ONELEVEL, attrs=["dnsRoot"], expression='(&(objectClass=crossRef)(dnsRoot=*))') new_realm = samdb.domain_dns_name() # go through and add the new realm for res_msg in res: # dnsRoot can be multi-valued, so only look for the old realm for dns_root in res_msg["dnsRoot"]: dns_root = str(dns_root) dn = res_msg.dn if old_realm in dns_root: new_dns_root = re.sub('%s$' % old_realm, new_realm, dns_root) logger.info("Adding %s dnsRoot to %s" % (new_dns_root, dn)) m = ldb.Message() m.dn = dn m["dnsRoot"] = ldb.MessageElement(new_dns_root, ldb.FLAG_MOD_ADD, "dnsRoot") samdb.modify(m) # optionally remove the dnsRoot for the old realm if delete_old_dns: logger.info("Removing %s dnsRoot from %s" % (dns_root, dn)) m["dnsRoot"] = ldb.MessageElement(dns_root, ldb.FLAG_MOD_DELETE, "dnsRoot") samdb.modify(m)
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): 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 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 get_ldif_for_editor(samdb, msg): # Copy the given message, because we do not # want to modify the original message. m = ldb.Message() m.dn = msg.dn for k in msg.keys(): if k == "dn": continue vals = msg[k] m[k] = vals need_base64 = False for v in vals: if is_printable_attr_val(v): continue need_base64 = True break if not need_base64: m[k].set_flags(ldb.FLAG_FORCE_NO_BASE64_LDIF) result_ldif = samdb.write_ldif(m, ldb.CHANGETYPE_NONE) return result_ldif
def err_dn_target_mismatch(self, dn, attrname, val, dsdb_dn, correct_dn, errstr): self.report( "ERROR: incorrect DN string component for %s in object %s - %s" % (attrname, dn, val)) dsdb_dn.dn = correct_dn if not self.confirm('Change DN to %s?' % str(dsdb_dn)): self.report("Not fixing %s" % errstr) return m = ldb.Message() m.dn = dn m['old_value'] = ldb.MessageElement(val, ldb.FLAG_MOD_DELETE, attrname) m['new_value'] = ldb.MessageElement(str(dsdb_dn), ldb.FLAG_MOD_ADD, attrname) if self.verbose: self.report(self.samdb.write_ldif(m, ldb.CHANGETYPE_MODIFY)) try: self.samdb.modify(m) except Exception, msg: self.report( "Failed to fix incorrect DN string on attribute %s : %s" % (attrname, msg)) return
def test_offline_manual_seized_ridalloc_add_user_as_admin(self): """Peform the same actions as test_offline_samba_tool_seized_ridalloc, but do not create the RID set. Confirm that user-add correctly creates the RID Set.""" 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) targetdir = self._test_join(fsmo_not_owner['dns_name'], "RIDALLOCTEST4") try: # Connect to the database ldb_url = "tdb://%s" % os.path.join(targetdir, "private/sam.ldb") lp = self.get_loadparm() new_ldb = SamDB(ldb_url, credentials=self.get_credentials(), session_info=admin_session( lp, self.ldb_dc1.get_domain_sid()), lp=lp) serviceName = new_ldb.get_dsServiceName() m = ldb.Message() m.dn = fsmo_dn m["fSMORoleOwner"] = ldb.MessageElement(serviceName, ldb.FLAG_MOD_REPLACE, "fSMORoleOwner") new_ldb.modify(m) # 1. Get server name res = new_ldb.search(base=ldb.Dn(new_ldb, new_ldb.get_serverName()), scope=ldb.SCOPE_BASE, attrs=["serverReference"]) # 2. Get server reference server_ref_dn = ldb.Dn(new_ldb, res[0]['serverReference'][0]) # Assert that no RID Set has been set res = new_ldb.search(base=server_ref_dn, scope=ldb.SCOPE_BASE, attrs=['rIDSetReferences']) self.assertFalse("rIDSetReferences" in res[0]) smbconf = os.path.join(targetdir, "etc/smb.conf") # Create a user to allocate a RID Set for itself (the RID master) new_ldb.newuser("ridalloctestuser", "P@ssword!") # 3. Assert we get the RID Set res = new_ldb.search(base=server_ref_dn, scope=ldb.SCOPE_BASE, attrs=['rIDSetReferences']) self.assertTrue("rIDSetReferences" in res[0]) finally: self._test_force_demote(fsmo_not_owner['dns_name'], "RIDALLOCTEST4") shutil.rmtree(targetdir, ignore_errors=True)
def test_change_primary_group(self): # # Wait for the primary group change for the created user. # messages = self.waitForMessages(2) print("Received %d messages" % len(messages)) self.assertEquals(2, len(messages), "Did not receive the expected number of messages") # Check the PrimaryGroup message audit = messages[0]["groupChange"] self.assertEqual("PrimaryGroup", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=domain users,cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") # Check the Add message for the new users primary group audit = messages[1]["groupChange"] self.assertEqual("Added", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=domain users,cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) self.assertEquals(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP, audit["eventId"]) # # Add the user to a group, the user needs to be a member of a group # before there primary group can be set to that group. # self.discardMessages() self.ldb.add_remove_group_members(GROUP_NAME_01, [USER_NAME]) messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) self.assertEquals(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] self.assertEqual("Added", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_01 + ",cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") self.assertEquals(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP, audit["eventId"]) # # Change the primary group of a user # user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_01 + ",cn=users," + self.base_dn # get the primaryGroupToken of the group res = self.ldb.search(base=group_dn, attrs=["primaryGroupToken"], scope=ldb.SCOPE_BASE) group_id = res[0]["primaryGroupToken"] # set primaryGroupID attribute of the user to that group m = ldb.Message() m.dn = ldb.Dn(self.ldb, user_dn) m["primaryGroupID"] = ldb.MessageElement(group_id, FLAG_MOD_REPLACE, "primaryGroupID") self.discardMessages() self.ldb.modify(m) # # Wait for the primary group change. # Will see the user removed from the new group # the user added to their old primary group # and a new primary group event. # messages = self.waitForMessages(3) print("Received %d messages" % len(messages)) self.assertEquals(3, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] self.assertEqual("Removed", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_01 + ",cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") self.assertEquals(EVT_ID_USER_REMOVED_FROM_GLOBAL_SEC_GROUP, audit["eventId"]) audit = messages[1]["groupChange"] self.assertEqual("Added", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=domain users,cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP") self.assertEquals(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP, audit["eventId"]) audit = messages[2]["groupChange"] self.assertEqual("PrimaryGroup", audit["action"]) user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn group_dn = "cn=" + GROUP_NAME_01 + ",cn=users," + self.base_dn self.assertTrue(user_dn.lower(), audit["user"].lower()) self.assertTrue(group_dn.lower(), audit["group"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "LDAP")
:param idmapdb: Samba4 IDMAP database :param samba3_idmap: Samba3 IDMAP database to import from :param logger: Logger object """ try: samba3_idmap = samba3.get_idmap_db() except IOError, e: logger.warn('Cannot open idmap database, Ignoring: %s', str(e)) return currentxid = max(samba3_idmap.get_user_hwm(), samba3_idmap.get_group_hwm()) lowerbound = currentxid # FIXME: upperbound m = ldb.Message() m.dn = ldb.Dn(idmapdb, 'CN=CONFIG') m['lowerbound'] = ldb.MessageElement(str(lowerbound), ldb.FLAG_MOD_REPLACE, 'lowerBound') m['xidNumber'] = ldb.MessageElement(str(currentxid), ldb.FLAG_MOD_REPLACE, 'xidNumber') idmapdb.modify(m) for id_type, xid in samba3_idmap.ids(): if id_type == 'UID': xid_type = 'ID_TYPE_UID' elif id_type == 'GID': xid_type = 'ID_TYPE_GID' else: logger.warn('Wrong type of entry in idmap (%s), Ignoring', id_type) continue
def test_msDSRevealedUsers_local_deny_allow(self): """ Ensure that the deny trumps allow, and we can modify these attributes directly instead of the global groups. This may fail on Windows due to tokenGroup calculation caching. """ rand = random.randint(1, 10000000) expected_user_attributes = [drsuapi.DRSUAPI_ATTID_lmPwdHistory, drsuapi.DRSUAPI_ATTID_supplementalCredentials, drsuapi.DRSUAPI_ATTID_ntPwdHistory, drsuapi.DRSUAPI_ATTID_unicodePwd, drsuapi.DRSUAPI_ATTID_dBCSPwd] # Add a user on DC1, add it to allowed password replication # group, and replicate to RODC with EXOP_REPL_SECRETS user_name = "test_rodcF_%s" % rand password = "******" user_dn = "CN=%s,%s" % (user_name, self.ou) self.ldb_dc1.add({ "dn": user_dn, "objectclass": "user", "sAMAccountName": user_name }) # Store some secret on this user self.ldb_dc1.setpassword("(sAMAccountName=%s)" % user_name, password, False, user_name) req10 = self._getnc_req10(dest_dsa=str(self.rodc_ctx.ntds_guid), invocation_id=self.ldb_dc1.get_invocation_id(), nc_dn_str=user_dn, exop=drsuapi.DRSUAPI_EXOP_REPL_SECRET, partial_attribute_set=drs_get_rodc_partial_attribute_set(self.ldb_dc1, self.tmp_samdb), max_objects=133, replica_flags=0) m = ldb.Message() m.dn = ldb.Dn(self.ldb_dc1, self.computer_dn) m["msDS-RevealOnDemandGroup"] = \ ldb.MessageElement(user_dn, ldb.FLAG_MOD_ADD, "msDS-RevealOnDemandGroup") self.ldb_dc1.modify(m) # In local allow, should be success try: (level, ctr) = self.rodc_drs.DsGetNCChanges(self.rodc_drs_handle, 10, req10) except: self.fail("Should have succeeded when in local allow group") self._assert_in_revealed_users(user_dn, expected_user_attributes) (self.rodc_drs, self.rodc_drs_handle) = self._ds_bind(self.dnsname_dc1, self.rodc_creds) m = ldb.Message() m.dn = ldb.Dn(self.ldb_dc1, self.computer_dn) m["msDS-NeverRevealGroup"] = \ ldb.MessageElement(user_dn, ldb.FLAG_MOD_ADD, "msDS-NeverRevealGroup") self.ldb_dc1.modify(m) # In local allow and deny, should be failure try: (level, ctr) = self.rodc_drs.DsGetNCChanges(self.rodc_drs_handle, 10, req10) self.fail("Successfully replicated secrets to an RODC that shouldn't have been replicated.") except WERRORError as e5: (enum, estr) = e5.args self.assertEqual(enum, 8630) # ERROR_DS_DRA_SECRETS_DENIED m = ldb.Message() m.dn = ldb.Dn(self.ldb_dc1, self.computer_dn) m["msDS-RevealOnDemandGroup"] = \ ldb.MessageElement(user_dn, ldb.FLAG_MOD_DELETE, "msDS-RevealOnDemandGroup") self.ldb_dc1.modify(m) # In local deny, should be failure (self.rodc_drs, self.rodc_drs_handle) = self._ds_bind(self.dnsname_dc1, self.rodc_creds) try: (level, ctr) = self.rodc_drs.DsGetNCChanges(self.rodc_drs_handle, 10, req10) self.fail("Successfully replicated secrets to an RODC that shouldn't have been replicated.") except WERRORError as e6: (enum, estr) = e6.args self.assertEqual(enum, 8630) # ERROR_DS_DRA_SECRETS_DENIED
def set_domain_pwdHistoryLength(self, value): m = ldb.Message() m.dn = ldb.Dn(self.ldb, self.ldb.domain_dn()) m["pwdHistoryLength"] = ldb.MessageElement(value, ldb.FLAG_MOD_REPLACE, "pwdHistoryLength") self.ldb.modify(m)
def newuser(self, username, password, force_password_change_at_next_login_req=False, useusernameascn=False, userou=None, surname=None, givenname=None, initials=None, profilepath=None, scriptpath=None, homedrive=None, homedirectory=None, jobtitle=None, department=None, company=None, description=None, mailaddress=None, internetaddress=None, telephonenumber=None, physicaldeliveryoffice=None, sd=None, setpassword=True, uidnumber=None, gidnumber=None, gecos=None, loginshell=None, uid=None, nisdomain=None, unixhome=None, smartcard_required=False): """Adds a new user with additional parameters :param username: Name of the new user :param password: Password for the new user :param force_password_change_at_next_login_req: Force password change :param useusernameascn: Use username as cn rather that firstname + initials + lastname :param userou: Object container (without domainDN postfix) for new user :param surname: Surname of the new user :param givenname: First name of the new user :param initials: Initials of the new user :param profilepath: Profile path of the new user :param scriptpath: Logon script path of the new user :param homedrive: Home drive of the new user :param homedirectory: Home directory of the new user :param jobtitle: Job title of the new user :param department: Department of the new user :param company: Company of the new user :param description: of the new user :param mailaddress: Email address of the new user :param internetaddress: Home page of the new user :param telephonenumber: Phone number of the new user :param physicaldeliveryoffice: Office location of the new user :param sd: security descriptor of the object :param setpassword: optionally disable password reset :param uidnumber: RFC2307 Unix numeric UID of the new user :param gidnumber: RFC2307 Unix primary GID of the new user :param gecos: RFC2307 Unix GECOS field of the new user :param loginshell: RFC2307 Unix login shell of the new user :param uid: RFC2307 Unix username of the new user :param nisdomain: RFC2307 Unix NIS domain of the new user :param unixhome: RFC2307 Unix home directory of the new user :param smartcard_required: set the UF_SMARTCARD_REQUIRED bit of the new user """ displayname = "" if givenname is not None: displayname += givenname if initials is not None: displayname += ' %s.' % initials if surname is not None: displayname += ' %s' % surname cn = username if useusernameascn is None and displayname != "": cn = displayname user_dn = "CN=%s,%s,%s" % (cn, (userou or "CN=Users"), self.domain_dn()) dnsdomain = ldb.Dn(self, self.domain_dn()).canonical_str().replace("/", "") user_principal_name = "%s@%s" % (username, dnsdomain) # The new user record. Note the reliance on the SAMLDB module which # fills in the default information ldbmessage = {"dn": user_dn, "sAMAccountName": username, "userPrincipalName": user_principal_name, "objectClass": "user"} if smartcard_required: ldbmessage["userAccountControl"] = str(dsdb.UF_NORMAL_ACCOUNT | dsdb.UF_SMARTCARD_REQUIRED) setpassword = False if surname is not None: ldbmessage["sn"] = surname if givenname is not None: ldbmessage["givenName"] = givenname if displayname != "": ldbmessage["displayName"] = displayname ldbmessage["name"] = displayname if initials is not None: ldbmessage["initials"] = '%s.' % initials if profilepath is not None: ldbmessage["profilePath"] = profilepath if scriptpath is not None: ldbmessage["scriptPath"] = scriptpath if homedrive is not None: ldbmessage["homeDrive"] = homedrive if homedirectory is not None: ldbmessage["homeDirectory"] = homedirectory if jobtitle is not None: ldbmessage["title"] = jobtitle if department is not None: ldbmessage["department"] = department if company is not None: ldbmessage["company"] = company if description is not None: ldbmessage["description"] = description if mailaddress is not None: ldbmessage["mail"] = mailaddress if internetaddress is not None: ldbmessage["wWWHomePage"] = internetaddress if telephonenumber is not None: ldbmessage["telephoneNumber"] = telephonenumber if physicaldeliveryoffice is not None: ldbmessage["physicalDeliveryOfficeName"] = physicaldeliveryoffice if sd is not None: ldbmessage["nTSecurityDescriptor"] = ndr_pack(sd) ldbmessage2 = None if any(map(lambda b: b is not None, (uid, uidnumber, gidnumber, gecos, loginshell, nisdomain, unixhome))): ldbmessage2 = ldb.Message() ldbmessage2.dn = ldb.Dn(self, user_dn) if uid is not None: ldbmessage2["uid"] = ldb.MessageElement(str(uid), ldb.FLAG_MOD_REPLACE, 'uid') if uidnumber is not None: ldbmessage2["uidNumber"] = ldb.MessageElement(str(uidnumber), ldb.FLAG_MOD_REPLACE, 'uidNumber') if gidnumber is not None: ldbmessage2["gidNumber"] = ldb.MessageElement(str(gidnumber), ldb.FLAG_MOD_REPLACE, 'gidNumber') if gecos is not None: ldbmessage2["gecos"] = ldb.MessageElement(str(gecos), ldb.FLAG_MOD_REPLACE, 'gecos') if loginshell is not None: ldbmessage2["loginShell"] = ldb.MessageElement(str(loginshell), ldb.FLAG_MOD_REPLACE, 'loginShell') if unixhome is not None: ldbmessage2["unixHomeDirectory"] = ldb.MessageElement( str(unixhome), ldb.FLAG_MOD_REPLACE, 'unixHomeDirectory') if nisdomain is not None: ldbmessage2["msSFU30NisDomain"] = ldb.MessageElement( str(nisdomain), ldb.FLAG_MOD_REPLACE, 'msSFU30NisDomain') ldbmessage2["msSFU30Name"] = ldb.MessageElement( str(username), ldb.FLAG_MOD_REPLACE, 'msSFU30Name') ldbmessage2["unixUserPassword"] = ldb.MessageElement( 'ABCD!efgh12345$67890', ldb.FLAG_MOD_REPLACE, 'unixUserPassword') self.transaction_start() try: self.add(ldbmessage) if ldbmessage2: self.modify(ldbmessage2) # Sets the password for it if setpassword: self.setpassword(("(distinguishedName=%s)" % ldb.binary_encode(user_dn)), password, force_password_change_at_next_login_req) except: self.transaction_cancel() raise else: self.transaction_commit()
def delete_attribute(self, dn, attr, value): """Deletes an attribute from an object""" m = ldb.Message() m.dn = ldb.Dn(self.test_ldb_dc, dn) m[attr] = ldb.MessageElement(value, ldb.FLAG_MOD_DELETE, attr) self.test_ldb_dc.modify(m)
def modify_object(self, dn, attr, value): """Modifies an object's USN by adding an attribute value to it""" m = ldb.Message() m.dn = ldb.Dn(self.test_ldb_dc, dn) m[attr] = ldb.MessageElement(value, ldb.FLAG_MOD_ADD, attr) self.test_ldb_dc.modify(m)
def add_linked_attribute(self, src, dest, attr='member', controls=None): m = ldb.Message() m.dn = ldb.Dn(self.samdb, src) m[attr] = ldb.MessageElement(dest, ldb.FLAG_MOD_ADD, attr) self.samdb.modify(m, controls=controls)
def test_modify_index_multi_valued_truncated_keys(self): # 0 1 2 3 4 5 # 12345678901234567890123456789012345678901234567890 # @INDEX:NOTUNIQUE:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aa_gt_max = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ab_gt_max = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab" bb_gt_max = b"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" cc_gt_max = b"cccccccccccccccccccccccccccccccccc" self.l.add({"dn": "OU=01,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG", "notUnique": [aa_gt_max, ab_gt_max, bb_gt_max], "objectUUID": b"0123456789abcde0"}) self.l.add({"dn": "OU=02,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG", "notUnique": [aa_gt_max, ab_gt_max, cc_gt_max], "objectUUID": b"0123456789abcde1"}) res = self.l.search( base="DC=SAMBA,DC=ORG", expression="(notUnique=" + aa_gt_max.decode("ascii") + ")") self.assertEquals(2, len(res)) self.assertTrue( contains(res, "OU=01,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG")) self.assertTrue( contains(res, "OU=02,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG")) # # Modify that does not change the indexed attribute # msg = ldb.Message() msg.dn = ldb.Dn(self.l, "OU=01,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG") msg["notUnique"] = ldb.MessageElement( [aa_gt_max, ab_gt_max, bb_gt_max], ldb.FLAG_MOD_REPLACE, "notUnique") self.l.modify(msg) # # As the modify is replacing the attribute with the same contents # there should be no changes to the indexes. # # # Modify that removes a value from the indexed attribute # msg = ldb.Message() msg.dn = ldb.Dn(self.l, "OU=01,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG") msg["notUnique"] = ldb.MessageElement( [aa_gt_max, bb_gt_max], ldb.FLAG_MOD_REPLACE, "notUnique") self.l.modify(msg) # # Modify that does a constrained delete the indexed attribute # msg = ldb.Message() msg.dn = ldb.Dn(self.l, "OU=02,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG") msg["notUnique"] = ldb.MessageElement( [ab_gt_max], ldb.FLAG_MOD_DELETE, "notUnique") self.l.modify(msg) # # Modify that does an unconstrained delete the indexed attribute # msg = ldb.Message() msg.dn = ldb.Dn(self.l, "OU=02,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG") msg["notUnique"] = ldb.MessageElement( [], ldb.FLAG_MOD_DELETE, "notUnique") self.l.modify(msg) # # Modify that adds a value to the indexed attribute # msg = ldb.Message() msg.dn = ldb.Dn(self.l, "OU=02,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG") msg["notUnique"] = ldb.MessageElement( [cc_gt_max], ldb.FLAG_MOD_ADD, "notUnique") self.l.modify(msg) # # Modify that adds a values to the indexed attribute # msg = ldb.Message() msg.dn = ldb.Dn(self.l, "OU=02,OU=MODIFY_NON_UNIQUE,DC=SAMBA,DC=ORG") msg["notUnique"] = ldb.MessageElement( [aa_gt_max, ab_gt_max], ldb.FLAG_MOD_ADD, "notUnique") self.l.modify(msg)
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)
def test_link_utdv_hwm(self): """Test verify the DRS_GET_ANC behavior.""" ou1 = "OU=get_anc1,%s" % self.ou self.ldb_dc1.add({"dn": ou1, "objectclass": "organizationalUnit"}) ou1_id = self._get_indentifier(self.ldb_dc1, ou1) ou2 = "OU=get_anc2,%s" % ou1 self.ldb_dc1.add({"dn": ou2, "objectclass": "organizationalUnit"}) ou2_id = self._get_indentifier(self.ldb_dc1, ou2) dc3 = "CN=test_anc_dc_%u,%s" % (random.randint(0, 4294967295), ou2) self.ldb_dc1.add({ "dn": dc3, "objectclass": "computer", "userAccountControl": "%d" % (samba.dsdb.UF_ACCOUNTDISABLE | samba.dsdb.UF_SERVER_TRUST_ACCOUNT) }) dc3_id = self._get_indentifier(self.ldb_dc1, dc3) (hwm1, utdv1) = self._check_replication([ou1, ou2, dc3], drsuapi.DRSUAPI_DRS_WRIT_REP) self._check_replication([ou1, ou2, dc3], drsuapi.DRSUAPI_DRS_WRIT_REP | drsuapi.DRSUAPI_DRS_GET_ANC) self._check_replication([dc3], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY) self._check_replication([ou1, ou2, dc3], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY | drsuapi.DRSUAPI_DRS_GET_ANC) m = ldb.Message() m.dn = ldb.Dn(self.ldb_dc1, ou1) m["displayName"] = ldb.MessageElement("OU1", ldb.FLAG_MOD_ADD, "displayName") self.ldb_dc1.modify(m) (hwm2, utdv2) = self._check_replication([ou2, dc3, ou1], drsuapi.DRSUAPI_DRS_WRIT_REP) self._check_replication([ou1, ou2, dc3], drsuapi.DRSUAPI_DRS_WRIT_REP | drsuapi.DRSUAPI_DRS_GET_ANC) self._check_replication([dc3], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY) self._check_replication([ou1, ou2, dc3], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY | drsuapi.DRSUAPI_DRS_GET_ANC) self._check_replication([ou1], drsuapi.DRSUAPI_DRS_WRIT_REP, highwatermark=hwm1) self._check_replication([ou1], drsuapi.DRSUAPI_DRS_WRIT_REP | drsuapi.DRSUAPI_DRS_GET_ANC, highwatermark=hwm1) self._check_replication([ou1], drsuapi.DRSUAPI_DRS_WRIT_REP | drsuapi.DRSUAPI_DRS_GET_ANC, uptodateness_vector=utdv1) m = ldb.Message() m.dn = ldb.Dn(self.ldb_dc1, ou2) m["displayName"] = ldb.MessageElement("OU2", ldb.FLAG_MOD_ADD, "displayName") self.ldb_dc1.modify(m) (hwm3, utdv3) = self._check_replication([dc3, ou1, ou2], drsuapi.DRSUAPI_DRS_WRIT_REP) self._check_replication([ou1, ou2, dc3], drsuapi.DRSUAPI_DRS_WRIT_REP | drsuapi.DRSUAPI_DRS_GET_ANC) self._check_replication([dc3], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY) self._check_replication([ou1, ou2, dc3], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY | drsuapi.DRSUAPI_DRS_GET_ANC) self._check_replication([ou1, ou2], drsuapi.DRSUAPI_DRS_WRIT_REP, highwatermark=hwm1) self._check_replication([ou1, ou2], drsuapi.DRSUAPI_DRS_WRIT_REP | drsuapi.DRSUAPI_DRS_GET_ANC, highwatermark=hwm1) self._check_replication([ou1, ou2], drsuapi.DRSUAPI_DRS_WRIT_REP | drsuapi.DRSUAPI_DRS_GET_ANC, uptodateness_vector=utdv1) m = ldb.Message() m.dn = ldb.Dn(self.ldb_dc1, self.ou) m["displayName"] = ldb.MessageElement("OU", ldb.FLAG_MOD_ADD, "displayName") self.ldb_dc1.modify(m) (hwm4, utdv4) = self._check_replication([dc3, ou1, ou2, self.ou], drsuapi.DRSUAPI_DRS_WRIT_REP) self._check_replication([self.ou, ou1, ou2, dc3], drsuapi.DRSUAPI_DRS_WRIT_REP | drsuapi.DRSUAPI_DRS_GET_ANC) self._check_replication([dc3], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY) self._check_replication([self.ou, ou1, ou2, dc3], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY | drsuapi.DRSUAPI_DRS_GET_ANC) self._check_replication([self.ou, ou2], drsuapi.DRSUAPI_DRS_WRIT_REP | drsuapi.DRSUAPI_DRS_GET_ANC, uptodateness_vector=utdv2) cn3 = "CN=get_anc3,%s" % ou2 self.ldb_dc1.add({ "dn": cn3, "objectclass": "container", }) cn3_id = self._get_indentifier(self.ldb_dc1, cn3) (hwm5, utdv5) = self._check_replication([dc3, ou1, ou2, self.ou, cn3], drsuapi.DRSUAPI_DRS_WRIT_REP) self._check_replication([self.ou, ou1, ou2, dc3, cn3], drsuapi.DRSUAPI_DRS_WRIT_REP | drsuapi.DRSUAPI_DRS_GET_ANC) self._check_replication([dc3], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY) self._check_replication([self.ou, ou1, ou2, dc3], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY | drsuapi.DRSUAPI_DRS_GET_ANC) m = ldb.Message() m.dn = ldb.Dn(self.ldb_dc1, ou2) m["managedBy"] = ldb.MessageElement(dc3, ldb.FLAG_MOD_ADD, "managedBy") self.ldb_dc1.modify(m) ou2_managedBy_dc3 = AbstractLink( drsuapi.DRSUAPI_ATTID_managedBy, drsuapi.DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE, ou2_id.guid, dc3_id.guid) (hwm6, utdv6) = self._check_replication([dc3, ou1, self.ou, cn3, ou2], drsuapi.DRSUAPI_DRS_WRIT_REP, expected_links=[ou2_managedBy_dc3]) # Can fail against Windows due to equal precedence of dc3, cn3 self._check_replication([self.ou, ou1, ou2, dc3, cn3], drsuapi.DRSUAPI_DRS_WRIT_REP | drsuapi.DRSUAPI_DRS_GET_ANC, expected_links=[ou2_managedBy_dc3]) self._check_replication([dc3], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY) self._check_replication([self.ou, ou1, ou2, dc3], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY | drsuapi.DRSUAPI_DRS_GET_ANC) self._check_replication([], drsuapi.DRSUAPI_DRS_WRIT_REP, uptodateness_vector=utdv5, expected_links=[ou2_managedBy_dc3]) self._check_replication([], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY, uptodateness_vector=utdv5) self._check_replication([], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY, uptodateness_vector=utdv5) m = ldb.Message() m.dn = ldb.Dn(self.ldb_dc1, dc3) m["managedBy"] = ldb.MessageElement(ou1, ldb.FLAG_MOD_ADD, "managedBy") self.ldb_dc1.modify(m) dc3_managedBy_ou1 = AbstractLink( drsuapi.DRSUAPI_ATTID_managedBy, drsuapi.DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE, dc3_id.guid, ou1_id.guid) (hwm7, utdv7) = self._check_replication( [ou1, self.ou, cn3, ou2, dc3], drsuapi.DRSUAPI_DRS_WRIT_REP, expected_links=[ou2_managedBy_dc3, dc3_managedBy_ou1]) # Can fail against Windows due to equal precedence of dc3, cn3 #self._check_replication([self.ou,ou1,ou2,dc3,cn3], # drsuapi.DRSUAPI_DRS_WRIT_REP| # drsuapi.DRSUAPI_DRS_GET_ANC, # expected_links=[ou2_managedBy_dc3,dc3_managedBy_ou1]) self._check_replication([dc3], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY, expected_links=[dc3_managedBy_ou1]) self._check_replication([dc3], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY, expected_links=[dc3_managedBy_ou1]) self._check_replication([self.ou, ou1, ou2, dc3], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY | drsuapi.DRSUAPI_DRS_GET_ANC, expected_links=[dc3_managedBy_ou1]) self._check_replication([dc3], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY, more_flags=drsuapi.DRSUAPI_DRS_GET_TGT, expected_links=[dc3_managedBy_ou1]) m = ldb.Message() m.dn = ldb.Dn(self.ldb_dc1, dc3) m["managedBy"] = ldb.MessageElement(ou2, ldb.FLAG_MOD_REPLACE, "managedBy") self.ldb_dc1.modify(m) dc3_managedBy_ou1.flags &= ~drsuapi.DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE dc3_managedBy_ou2 = AbstractLink( drsuapi.DRSUAPI_ATTID_managedBy, drsuapi.DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE, dc3_id.guid, ou2_id.guid) (hwm8, utdv8) = self._check_replication([ou1, self.ou, cn3, ou2, dc3], drsuapi.DRSUAPI_DRS_WRIT_REP, expected_links=[ ou2_managedBy_dc3, dc3_managedBy_ou1, dc3_managedBy_ou2 ]) # Can fail against Windows due to equal precedence of dc3, cn3 #self._check_replication([self.ou,ou1,ou2,dc3,cn3], # drsuapi.DRSUAPI_DRS_WRIT_REP| # drsuapi.DRSUAPI_DRS_GET_ANC, # expected_links=[ou2_managedBy_dc3,dc3_managedBy_ou1,dc3_managedBy_ou2]) self._check_replication( [dc3], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY, expected_links=[dc3_managedBy_ou1, dc3_managedBy_ou2]) self._check_replication( [self.ou, ou1, ou2, dc3], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY | drsuapi.DRSUAPI_DRS_GET_ANC, expected_links=[dc3_managedBy_ou1, dc3_managedBy_ou2]) self._check_replication( [dc3], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY, more_flags=drsuapi.DRSUAPI_DRS_GET_TGT, expected_links=[dc3_managedBy_ou1, dc3_managedBy_ou2]) self._check_replication( [], drsuapi.DRSUAPI_DRS_WRIT_REP, expected_links=[dc3_managedBy_ou1, dc3_managedBy_ou2], highwatermark=hwm7) self._check_replication( [], drsuapi.DRSUAPI_DRS_WRIT_REP | drsuapi.DRSUAPI_DRS_GET_ANC, expected_links=[dc3_managedBy_ou1, dc3_managedBy_ou2], highwatermark=hwm7) self._check_replication( [], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY, expected_links=[dc3_managedBy_ou1, dc3_managedBy_ou2], highwatermark=hwm7) self._check_replication( [], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY | drsuapi.DRSUAPI_DRS_GET_ANC, expected_links=[dc3_managedBy_ou1, dc3_managedBy_ou2], highwatermark=hwm7) self._check_replication( [], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY, more_flags=drsuapi.DRSUAPI_DRS_GET_TGT, expected_links=[dc3_managedBy_ou1, dc3_managedBy_ou2], highwatermark=hwm7) self._check_replication( [], drsuapi.DRSUAPI_DRS_WRIT_REP, expected_links=[dc3_managedBy_ou1, dc3_managedBy_ou2], uptodateness_vector=utdv7) self._check_replication( [], drsuapi.DRSUAPI_DRS_WRIT_REP | drsuapi.DRSUAPI_DRS_GET_ANC, expected_links=[dc3_managedBy_ou1, dc3_managedBy_ou2], uptodateness_vector=utdv7) self._check_replication( [], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY, expected_links=[dc3_managedBy_ou1, dc3_managedBy_ou2], uptodateness_vector=utdv7) self._check_replication( [], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY | drsuapi.DRSUAPI_DRS_GET_ANC, expected_links=[dc3_managedBy_ou1, dc3_managedBy_ou2], uptodateness_vector=utdv7) self._check_replication( [], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY, more_flags=drsuapi.DRSUAPI_DRS_GET_TGT, expected_links=[dc3_managedBy_ou1, dc3_managedBy_ou2], uptodateness_vector=utdv7)
def test_link_utdv_hwm(self): ou1 = "OU=get_anc1,%s" % self.ou self.ldb_dc1.add({"dn": ou1, "objectclass": "organizationalUnit"}) ou1_id = self._get_indentifier(self.ldb_dc1, ou1) ou2 = "OU=get_anc2,%s" % ou1 self.ldb_dc1.add({"dn": ou2, "objectclass": "organizationalUnit"}) ou2_id = self._get_indentifier(self.ldb_dc1, ou2) dc3 = "CN=test_anc_dc_%u,%s" % (random.randint(0, 4294967295), ou2) self.ldb_dc1.add({ "dn": dc3, "objectclass": "computer", "userAccountControl": "%d" % (samba.dsdb.UF_ACCOUNTDISABLE | samba.dsdb.UF_SERVER_TRUST_ACCOUNT) }) dc3_id = self._get_indentifier(self.ldb_dc1, dc3) cn3 = "CN=get_anc3,%s" % ou2 self.ldb_dc1.add({ "dn": cn3, "objectclass": "container", }) cn3_id = self._get_indentifier(self.ldb_dc1, cn3) m = ldb.Message() m.dn = ldb.Dn(self.ldb_dc1, ou1) m["managedBy"] = ldb.MessageElement(dc3, ldb.FLAG_MOD_ADD, "managedBy") self.ldb_dc1.modify(m) ou1_managedBy_dc3 = AbstractLink( drsuapi.DRSUAPI_ATTID_managedBy, drsuapi.DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE, ou1_id.guid, dc3_id.guid) (hwm0, utdv0) = self._check_replication([ou2, dc3, cn3, ou1], drsuapi.DRSUAPI_DRS_WRIT_REP, expected_links=[ou1_managedBy_dc3], nc_object_count=4) m = ldb.Message() m.dn = ldb.Dn(self.ldb_dc1, dc3) m["managedBy"] = ldb.MessageElement(ou2, ldb.FLAG_MOD_ADD, "managedBy") self.ldb_dc1.modify(m) dc3_managedBy_ou2 = AbstractLink( drsuapi.DRSUAPI_ATTID_managedBy, drsuapi.DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE, dc3_id.guid, ou2_id.guid) self._check_replication([], drsuapi.DRSUAPI_DRS_WRIT_REP, expected_links=[dc3_managedBy_ou2], highwatermark=hwm0, nc_object_count=1) self._check_replication([], drsuapi.DRSUAPI_DRS_WRIT_REP | drsuapi.DRSUAPI_DRS_GET_ANC, expected_links=[dc3_managedBy_ou2], highwatermark=hwm0, nc_object_count=1) self._check_replication([], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY, expected_links=[dc3_managedBy_ou2], highwatermark=hwm0, nc_object_count=1) self._check_replication([], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY | drsuapi.DRSUAPI_DRS_GET_ANC, expected_links=[dc3_managedBy_ou2], highwatermark=hwm0, nc_object_count=1) self._check_replication([], drsuapi.DRSUAPI_DRS_WRIT_REP, expected_links=[dc3_managedBy_ou2], uptodateness_vector=utdv0, nc_object_count=4) self._check_replication([], drsuapi.DRSUAPI_DRS_WRIT_REP | drsuapi.DRSUAPI_DRS_GET_ANC, expected_links=[dc3_managedBy_ou2], uptodateness_vector=utdv0, nc_object_count=4) self._check_replication([], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY, expected_links=[dc3_managedBy_ou2], uptodateness_vector=utdv0, nc_object_count=1) self._check_replication([], drsuapi.DRSUAPI_DRS_CRITICAL_ONLY | drsuapi.DRSUAPI_DRS_GET_ANC, expected_links=[dc3_managedBy_ou2], uptodateness_vector=utdv0, nc_object_count=1)
def test_rid_set_dbcheck(self): """Perform a join against the RID manager and assert we have a RID Set. Using dbcheck, we assert that we can detect out of range users.""" 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) targetdir = self._test_join(fsmo_owner['dns_name'], "RIDALLOCTEST6") try: # Connect to the database ldb_url = "tdb://%s" % os.path.join(targetdir, "private/sam.ldb") smbconf = os.path.join(targetdir, "etc/smb.conf") lp = self.get_loadparm() new_ldb = SamDB(ldb_url, credentials=self.get_credentials(), session_info=system_session(lp), lp=lp) # 1. Get server name res = new_ldb.search(base=ldb.Dn(new_ldb, new_ldb.get_serverName()), scope=ldb.SCOPE_BASE, attrs=["serverReference"]) # 2. Get server reference server_ref_dn = ldb.Dn(new_ldb, res[0]['serverReference'][0]) # 3. Assert we get the RID Set res = new_ldb.search(base=server_ref_dn, scope=ldb.SCOPE_BASE, attrs=['rIDSetReferences']) self.assertTrue("rIDSetReferences" in res[0]) rid_set_dn = ldb.Dn(new_ldb, res[0]["rIDSetReferences"][0]) # 4. Add a new user (triggers RID set work) new_ldb.newuser("ridalloctestuser", "P@ssword!") # 5. Now fetch the RID SET rid_set_res = new_ldb.search( base=rid_set_dn, scope=ldb.SCOPE_BASE, attrs=['rIDNextRid', 'rIDAllocationPool']) next_pool = int(rid_set_res[0]["rIDAllocationPool"][0]) last_rid = (0xFFFFFFFF00000000 & next_pool) >> 32 # 6. Add user above the ridNextRid and at mid-range. # # We can do this with safety because this is an offline DB that will be # destroyed. m = ldb.Message() m.dn = ldb.Dn(new_ldb, "CN=ridsettestuser1,CN=Users") m.dn.add_base(new_ldb.get_default_basedn()) m['objectClass'] = ldb.MessageElement('user', ldb.FLAG_MOD_ADD, 'objectClass') m['objectSid'] = ldb.MessageElement( ndr_pack( security.dom_sid( str(new_ldb.get_domain_sid()) + "-%d" % (last_rid - 10))), ldb.FLAG_MOD_ADD, 'objectSid') new_ldb.add(m, controls=["relax:0"]) # 7. Check the RID Set chk = dbcheck(new_ldb, verbose=False, fix=True, yes=True, quiet=True) # Should have one error (wrong rIDNextRID) self.assertEqual( chk.check_database(DN=rid_set_dn, scope=ldb.SCOPE_BASE), 1) # 8. Assert we get didn't show any other errors chk = dbcheck(new_ldb, verbose=False, fix=False, quiet=True) rid_set_res = new_ldb.search( base=rid_set_dn, scope=ldb.SCOPE_BASE, attrs=['rIDNextRid', 'rIDAllocationPool']) last_allocated_rid = int(rid_set_res[0]["rIDNextRid"][0]) self.assertEquals(last_allocated_rid, last_rid - 10) # 9. Assert that the range wasn't thrown away next_pool = int(rid_set_res[0]["rIDAllocationPool"][0]) self.assertEqual(last_rid, (0xFFFFFFFF00000000 & next_pool) >> 32, "rid pool should have changed") finally: self._test_force_demote(fsmo_owner['dns_name'], "RIDALLOCTEST6") shutil.rmtree(targetdir, ignore_errors=True)
def update_secrets(newsecrets_ldb, secrets_ldb, messagefunc): """Update secrets.ldb :param newsecrets_ldb: An LDB object that is connected to the secrets.ldb of the reference provision :param secrets_ldb: An LDB object that is connected to the secrets.ldb of the updated provision """ messagefunc(SIMPLE, "Update of secrets.ldb") reference = newsecrets_ldb.search(base="@MODULES", scope=SCOPE_BASE) current = secrets_ldb.search(base="@MODULES", scope=SCOPE_BASE) assert reference, "Reference modules list can not be empty" if len(current) == 0: # No modules present delta = secrets_ldb.msg_diff(ldb.Message(), reference[0]) delta.dn = reference[0].dn secrets_ldb.add(reference[0]) else: delta = secrets_ldb.msg_diff(current[0], reference[0]) delta.dn = current[0].dn secrets_ldb.modify(delta) reference = newsecrets_ldb.search(expression="objectClass=top", base="", scope=SCOPE_SUBTREE, attrs=["dn"]) current = secrets_ldb.search(expression="objectClass=top", base="", scope=SCOPE_SUBTREE, attrs=["dn"]) hash_new = {} hash = {} listMissing = [] listPresent = [] empty = ldb.Message() for i in range(0, len(reference)): hash_new[str(reference[i]["dn"]).lower()] = reference[i]["dn"] # Create a hash for speeding the search of existing object in the # current provision for i in range(0, len(current)): hash[str(current[i]["dn"]).lower()] = current[i]["dn"] for k in hash_new.keys(): if not hash.has_key(k): listMissing.append(hash_new[k]) else: listPresent.append(hash_new[k]) for entry in listMissing: reference = newsecrets_ldb.search(expression="distinguishedName=%s" % entry, base="", scope=SCOPE_SUBTREE) current = secrets_ldb.search(expression="distinguishedName=%s" % entry, base="", scope=SCOPE_SUBTREE) delta = secrets_ldb.msg_diff(empty, reference[0]) for att in hashAttrNotCopied: delta.remove(att) messagefunc(CHANGE, "Entry %s is missing from secrets.ldb" % reference[0].dn) for att in delta: messagefunc(CHANGE, " Adding attribute %s" % att) delta.dn = reference[0].dn secrets_ldb.add(delta) for entry in listPresent: reference = newsecrets_ldb.search(expression="distinguishedName=%s" % entry, base="", scope=SCOPE_SUBTREE) current = secrets_ldb.search(expression="distinguishedName=%s" % entry, base="", scope=SCOPE_SUBTREE) delta = secrets_ldb.msg_diff(current[0], reference[0]) for att in hashAttrNotCopied: delta.remove(att) for att in delta: if att == "name": messagefunc(CHANGE, "Found attribute name on %s," " must rename the DN" % (current[0].dn)) identic_rename(secrets_ldb, reference[0].dn) else: delta.remove(att) for entry in listPresent: reference = newsecrets_ldb.search(expression="distinguishedName=%s" % entry, base="", scope=SCOPE_SUBTREE) current = secrets_ldb.search(expression="distinguishedName=%s" % entry, base="", scope=SCOPE_SUBTREE) delta = secrets_ldb.msg_diff(current[0], reference[0]) for att in hashAttrNotCopied: delta.remove(att) for att in delta: if att == "msDS-KeyVersionNumber": delta.remove(att) if att != "dn": messagefunc(CHANGE, "Adding/Changing attribute %s to %s" % (att, current[0].dn)) delta.dn = current[0].dn secrets_ldb.modify(delta) res2 = secrets_ldb.search(expression="(samaccountname=dns)", scope=SCOPE_SUBTREE, attrs=["dn"]) if len(res2) == 1: messagefunc(SIMPLE, "Remove old dns account") secrets_ldb.delete(res2[0]["dn"])
def test_rid_set_dbcheck_after_seize(self): """Perform a join against the RID manager and assert we have a RID Set. We seize the RID master role, then using dbcheck, we assert that we can detect out of range users (and then bump the RID set as required).""" 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) targetdir = self._test_join(fsmo_owner['dns_name'], "RIDALLOCTEST7") try: # Connect to the database ldb_url = "tdb://%s" % os.path.join(targetdir, "private/sam.ldb") smbconf = os.path.join(targetdir, "etc/smb.conf") lp = self.get_loadparm() new_ldb = SamDB(ldb_url, credentials=self.get_credentials(), session_info=system_session(lp), lp=lp) # 1. Get server name res = new_ldb.search(base=ldb.Dn(new_ldb, new_ldb.get_serverName()), scope=ldb.SCOPE_BASE, attrs=["serverReference"]) # 2. Get server reference server_ref_dn = ldb.Dn(new_ldb, res[0]['serverReference'][0]) # 3. Assert we get the RID Set res = new_ldb.search(base=server_ref_dn, scope=ldb.SCOPE_BASE, attrs=['rIDSetReferences']) self.assertTrue("rIDSetReferences" in res[0]) rid_set_dn = ldb.Dn(new_ldb, res[0]["rIDSetReferences"][0]) # 4. Seize the RID Manager role (result, out, err) = self.runsubcmd("fsmo", "seize", "--role", "rid", "-H", ldb_url, "-s", smbconf, "--force") self.assertCmdSuccess(result, out, err) self.assertEquals(err, "", "Shouldn't be any error messages") # 5. Add a new user (triggers RID set work) new_ldb.newuser("ridalloctestuser", "P@ssword!") # 6. Now fetch the RID SET rid_set_res = new_ldb.search( base=rid_set_dn, scope=ldb.SCOPE_BASE, attrs=['rIDNextRid', 'rIDAllocationPool']) next_pool = int(rid_set_res[0]["rIDAllocationPool"][0]) last_rid = (0xFFFFFFFF00000000 & next_pool) >> 32 # 7. Add user above the ridNextRid and at almost the end of the range. # m = ldb.Message() m.dn = ldb.Dn(new_ldb, "CN=ridsettestuser2,CN=Users") m.dn.add_base(new_ldb.get_default_basedn()) m['objectClass'] = ldb.MessageElement('user', ldb.FLAG_MOD_ADD, 'objectClass') m['objectSid'] = ldb.MessageElement( ndr_pack( security.dom_sid( str(new_ldb.get_domain_sid()) + "-%d" % (last_rid - 3))), ldb.FLAG_MOD_ADD, 'objectSid') new_ldb.add(m, controls=["relax:0"]) # 8. Add user above the ridNextRid and at the end of the range m = ldb.Message() m.dn = ldb.Dn(new_ldb, "CN=ridsettestuser3,CN=Users") m.dn.add_base(new_ldb.get_default_basedn()) m['objectClass'] = ldb.MessageElement('user', ldb.FLAG_MOD_ADD, 'objectClass') m['objectSid'] = ldb.MessageElement( ndr_pack( security.dom_sid( str(new_ldb.get_domain_sid()) + "-%d" % last_rid)), ldb.FLAG_MOD_ADD, 'objectSid') new_ldb.add(m, controls=["relax:0"]) chk = dbcheck(new_ldb, verbose=False, fix=True, yes=True, quiet=True) # Should have fixed two errors (wrong ridNextRid) self.assertEqual( chk.check_database(DN=rid_set_dn, scope=ldb.SCOPE_BASE), 2) # 9. Assert we get didn't show any other errors chk = dbcheck(new_ldb, verbose=False, fix=False, quiet=True) # 10. Add another user (checks RID rollover) # We have seized the role, so we can do that. new_ldb.newuser("ridalloctestuser3", "P@ssword!") rid_set_res = new_ldb.search( base=rid_set_dn, scope=ldb.SCOPE_BASE, attrs=['rIDNextRid', 'rIDAllocationPool']) next_pool = int(rid_set_res[0]["rIDAllocationPool"][0]) self.assertNotEqual(last_rid, (0xFFFFFFFF00000000 & next_pool) >> 32, "rid pool should have changed") finally: self._test_force_demote(fsmo_owner['dns_name'], "RIDALLOCTEST7") shutil.rmtree(targetdir, ignore_errors=True)