def run(self, name, password=None, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp ) net = Net(creds, lp, server=credopts.ipaddress) net.create_user(name) if password is not None: net.set_password(name, creds.get_domain(), password, creds)
def netcmd_get_domain_infos_via_cldap(lp, creds, address=None): '''Return domain informations (CLDAP record) of the ldap-capable DC with the specified address''' net = Net(creds=creds, lp=lp) cldap_ret = net.finddc(address=address, flags=nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS) return cldap_ret
def test_admin_change_password(self): def isLastExpectedMessage(msg): return (msg["type"] == "Authentication" and msg["Authentication"]["status"] == "NT_STATUS_OK" and msg["Authentication"]["serviceDescription"] == "SAMR Password Change" and msg["Authentication"]["authDescription"] == "samr_ChangePasswordUser3") creds = self.insta_creds(template = self.get_credentials()) lp = self.get_loadparm() net = Net(creds, lp, server=self.server_ip) password = "******" net.change_password(newpassword=password.encode('utf-8'), username=USER_NAME, oldpassword=USER_PASS) messages = self.waitForMessages(isLastExpectedMessage) print "Received %d messages" % len(messages) self.assertEquals(8, len(messages), "Did not receive the expected number of messages")
def test_admin_change_password_bad_original_password(self): def isLastExpectedMessage(msg): return ((msg["type"] == "Authentication") and (msg["Authentication"]["status"] == "NT_STATUS_WRONG_PASSWORD") and (msg["Authentication"]["serviceDescription"] == "SAMR Password Change") and (msg["Authentication"]["authDescription"] == "samr_ChangePasswordUser3")) creds = self.insta_creds(template=self.get_credentials()) lp = self.get_loadparm() net = Net(creds, lp, server=self.server_ip) password = "******" exception_thrown = False try: net.change_password(newpassword=password.encode('utf-8'), oldpassword="******", username=USER_NAME) except Exception: exception_thrown = True self.assertEquals(True, exception_thrown, "Expected exception not thrown") messages = self.waitForMessages(isLastExpectedMessage) self.assertEquals(8, len(messages), "Did not receive the expected number of messages")
def run(self, domain, role=None, sambaopts=None, credopts=None, versionopts=None, server=None, site=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) net = Net(creds, lp, server=credopts.ipaddress) if site is None: site = "Default-First-Site-Name" netbios_name = lp.get("netbios name") if not role is None: role = role.upper() if role is None or role == "MEMBER": secure_channel_type = SEC_CHAN_WKSTA elif role == "DC": join_DC(server=server, creds=creds, lp=lp, domain=domain, site=site, netbios_name=netbios_name) return elif role == "RODC": join_RODC(server=server, creds=creds, lp=lp, domain=domain, site=site, netbios_name=netbios_name) return else: raise CommandError("Invalid role %s (possible values: MEMBER, BDC, RODC)" % role) (join_password, sid, domain_name) = net.join(domain, netbios_name, secure_channel_type, LIBNET_JOIN_AUTOMATIC) self.outf.write("Joined domain %s (%s)\n" % (domain_name, sid))
def run(self, credopts=None, sambaopts=None, versionopts=None, newpassword=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) # get old password now, to get the password prompts in the right order old_password = creds.get_password() net = Net(creds, lp, server=credopts.ipaddress) password = newpassword while True: if password is not None and password is not '': break password = getpass("New Password: "******"Retype Password: "******"Sorry, passwords do not match.\n") try: net.change_password(password) except Exception, msg: # FIXME: catch more specific exception raise CommandError("Failed to change password : {0!s}".format(msg))
def run(self, server_name=None, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) net = Net(creds, lp, server=credopts.ipaddress) if server_name is None: server_name = common.netcmd_dnsname(lp) self.outf.write(net.time(server_name)+"\n")
def netcmd_finddc(lp, creds): '''return domain-name of a writable/ldap-capable DC for the domain.''' net = Net(creds=creds, lp=lp) realm = lp.get('realm') cldap_ret = net.finddc(realm, nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE) return cldap_ret.pdc_dns_name
def run(self, domain, target_dir=None, credopts=None, sambaopts=None, versionopts=None, force=False): if not force: raise CommandError("samba-tool vampire is deprecated, please use samba-tool domain join. Use --force to override") lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) net = Net(creds, lp, server=credopts.ipaddress) (domain_name, domain_sid) = net.vampire(domain=domain, target_dir=target_dir) self.outf.write("Vampired domain %s (%s)\n" % (domain_name, domain_sid))
def packet_cldap_3(packet, conversation, context): # searchRequest net = Net(creds=context.creds, lp=context.lp) net.finddc(domain=context.lp.get('realm'), flags=(nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE)) return True
def run(self, name, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) net = Net(creds, lp, server=credopts.ipaddress) try: net.delete_user(name) except RuntimeError, msg: raise CommandError("Failed to delete user %s: %s" % (name, msg))
def run(self, displayname, H=None, tmpdir=None, sambaopts=None, credopts=None, versionopts=None): self.lp = sambaopts.get_loadparm() self.creds = credopts.get_credentials(self.lp, fallback_machine=True) net = Net(creds=self.creds, lp=self.lp) # We need to know writable DC to setup SMB connection if H and H.startswith('ldap://'): dc_hostname = H[7:] self.url = H flags = (nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE) cldap_ret = net.finddc(address=dc_hostname, flags=flags) else: flags = (nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE) cldap_ret = net.finddc(domain=self.lp.get('realm'), flags=flags) dc_hostname = cldap_ret.pdc_dns_name self.url = dc_url(self.lp, self.creds, dc=dc_hostname) samdb_connect(self) msg = get_gpo_info(self.samdb, displayname=displayname) if msg.count > 0: raise CommandError("A GPO already existing with name '{0!s}'".format(displayname)) # Create new GUID guid = str(uuid.uuid4()) gpo = "{{{0!s}}}".format(guid.upper()) realm = cldap_ret.dns_domain unc_path = "\\\\{0!s}\\sysvol\\{1!s}\\Policies\\{2!s}".format(realm, realm, gpo) # Create GPT if tmpdir is None: tmpdir = "/tmp" if not os.path.isdir(tmpdir): raise CommandError("Temporary directory '{0!s}' does not exist".format(tmpdir)) localdir = os.path.join(tmpdir, "policy") if not os.path.isdir(localdir): os.mkdir(localdir) gpodir = os.path.join(localdir, gpo) if os.path.isdir(gpodir): raise CommandError("GPO directory '{0!s}' already exists, refusing to overwrite".format(gpodir)) try: os.mkdir(gpodir) os.mkdir(os.path.join(gpodir, "Machine")) os.mkdir(os.path.join(gpodir, "User")) gpt_contents = "[General]\r\nVersion=0\r\n" file(os.path.join(gpodir, "GPT.INI"), "w").write(gpt_contents) except Exception, e: raise CommandError("Error Creating GPO files", e)
def get_ldb_url(lp, creds, names): if names.serverrole == "member server": net = Net(creds, lp) dc = net.finddc(domain=names.dnsdomain, flags=nbt.NBT_SERVER_LDAP) url = "ldap://" + dc.pdc_dns_name else: url = lp.samdb_url() return url
def netcmd_finddc(lp, creds, realm=None): """Return domain-name of a writable/ldap-capable DC for the default domain (parameter "realm" in smb.conf) unless another realm has been specified as argument""" net = Net(creds=creds, lp=lp) if realm is None: realm = lp.get("realm") cldap_ret = net.finddc(domain=realm, flags=nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE) return cldap_ret.pdc_dns_name
def test_export_keytab(self): net = Net(None, self.lp) net.export_keytab(keytab=self.ktfile, principal=self.principal) assert os.path.exists(self.ktfile), 'keytab was not created' with open_bytes(self.ktfile) as bytes_kt: result = '' for c in bytes_kt.read(): if c in string.printable: result += c principal_parts = self.principal.split('@') assert principal_parts[0] in result and \ principal_parts[1] in result, \ 'Principal not found in generated keytab'
def run(self, domain, role=None, sambaopts=None, credopts=None, versionopts=None, server=None, site=None, targetdir=None, domain_critical_only=False, parent_domain=None, machinepass=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) net = Net(creds, lp, server=credopts.ipaddress) if site is None: site = "Default-First-Site-Name" netbios_name = lp.get("netbios name") if not role is None: role = role.upper() if role is None or role == "MEMBER": (join_password, sid, domain_name) = net.join_member(domain, netbios_name, LIBNET_JOIN_AUTOMATIC, machinepass=machinepass) self.outf.write("Joined domain %s (%s)\n" % (domain_name, sid)) return elif role == "DC": join_DC(server=server, creds=creds, lp=lp, domain=domain, site=site, netbios_name=netbios_name, targetdir=targetdir, domain_critical_only=domain_critical_only, machinepass=machinepass) return elif role == "RODC": join_RODC(server=server, creds=creds, lp=lp, domain=domain, site=site, netbios_name=netbios_name, targetdir=targetdir, domain_critical_only=domain_critical_only, machinepass=machinepass) return elif role == "SUBDOMAIN": netbios_domain = lp.get("workgroup") if parent_domain is None: parent_domain = ".".join(domain.split(".")[1:]) join_subdomain(server=server, creds=creds, lp=lp, dnsdomain=domain, parent_domain=parent_domain, site=site, netbios_name=netbios_name, netbios_domain=netbios_domain, targetdir=targetdir, machinepass=machinepass) return else: raise CommandError("Invalid role '%s' (possible values: MEMBER, DC, RODC, SUBDOMAIN)" % role)
def __init__(self, binding_string, lp, creds, samdb, invocation_id): self.drs = drsuapi.drsuapi(binding_string, lp, creds) (self.drs_handle, self.supported_extensions) = drs_DsBind(self.drs) self.net = Net(creds=creds, lp=lp) self.samdb = samdb if not isinstance(invocation_id, misc.GUID): raise RuntimeError("Must supply GUID for invocation_id") if invocation_id == misc.GUID("00000000-0000-0000-0000-000000000000"): raise RuntimeError("Must not set GUID 00000000-0000-0000-0000-000000000000 as invocation_id") self.replication_state = self.net.replicate_init(self.samdb, lp, self.drs, invocation_id)
def test_net_change_password(self): dn = "CN=" + USER_NAME + ",CN=Users," + self.base_dn self.discardSetupMessages(dn) creds = self.insta_creds(template=self.get_credentials()) lp = self.get_loadparm() net = Net(creds, lp, server=self.server) password = "******" net.change_password(newpassword=password.encode('utf-8'), username=USER_NAME, oldpassword=USER_PASS) messages = self.waitForMessages(1, net, dn=dn) print("Received %d messages" % len(messages)) self.assertEquals(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["dsdbChange"] self.assertEquals("Modify", audit["operation"]) self.assertFalse(audit["performedAsSystem"]) self.assertTrue(dn.lower(), audit["dn"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) # We skip the check for self.get_service_description() as this # is subject to a race between smbd and the s4 rpc_server code # as to which will set the description as it is DCE/RPC over SMB self.assertTrue(self.is_guid(audit["transactionId"])) attributes = audit["attributes"] self.assertEquals(1, len(attributes)) actions = attributes["clearTextPassword"]["actions"] self.assertEquals(1, len(actions)) self.assertTrue(actions[0]["redacted"]) self.assertEquals("replace", actions[0]["action"])
def run(self, credopts=None, sambaopts=None, versionopts=None, newpassword=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) # get old password now, to get the password prompts in the right order old_password = creds.get_password() net = Net(creds, lp, server=credopts.ipaddress) password = newpassword while 1: if password is not None and password is not '': break password = getpass("New Password: "******"Failed to change password : %s" % msg)
def test_net_join(self): netbios_name = "NetJoinTest" machinepass = "******" creds = self.insta_creds(template=self.get_credentials(), kerberos_state=DONT_USE_KERBEROS) net = Net(creds, self.lp, server=self.server) # NOTE WELL: We must not run more than one successful # net.join_member per file (process), as the shared # secrets.ldb handle will be kept between runs. try: (join_password, sid, domain_name) = net.join_member( self.domain, netbios_name, LIBNET_JOIN_AUTOMATIC, machinepass=machinepass) except NTSTATUSError as e: code = ctypes.c_uint32(e[0]).value if code == ntstatus.NT_STATUS_CONNECTION_DISCONNECTED: self.fail("Connection failure") raise os.unlink(os.path.join(self.tempdir, "secrets.ldb")) pass
def test_net_join_no_spnego(self): self.lp.set("client use spnego", "no") netbios_name = "NetJoinNoSpnego" machinepass = "******" creds = self.insta_creds(template=self.get_credentials(), kerberos_state=DONT_USE_KERBEROS) net = Net(creds, self.lp, server=self.server) try: (join_password, sid, domain_name) = net.join_member( self.domain, netbios_name, LIBNET_JOIN_AUTOMATIC, machinepass=machinepass) except NTSTATUSError as e: code = ctypes.c_uint32(e.args[0]).value if code == ntstatus.NT_STATUS_CONNECTION_DISCONNECTED: self.fail("Connection failure") elif code == ntstatus.NT_STATUS_ACCESS_DENIED: return else: raise self.fail("Shoud have rejected NTLMv2 without SPNEGO")
def run(self, credopts=None, sambaopts=None, versionopts=None, newpassword=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) connect_password = "" if len(creds.get_user_to_connect()) > 0: connect_password = getpass("Password for [%s\\%s]: " % ( creds.get_user_to_connect_domain(), creds.get_user_to_connect()) ) creds.set_password_to_connect(connect_password) # get old password now, to get the password prompts in the right order old_password = creds.get_password() if len(creds.get_user_to_connect()) < 1: connect_password = old_password import pdb; pdb.set_trace() net = Net(creds, lp, server=credopts.ipaddress) password = newpassword while True: if password is not None and password is not '': break password = getpass("New Password: "******"Retype Password: "******"Sorry, passwords do not match.\n") try: net.change_password(password) except Exception, msg: # FIXME: catch more specific exception raise CommandError("Failed to change password : %s" % msg)
def test_admin_change_password_bad_original_password(self): def isLastExpectedMessage(msg): return (msg["type"] == "Authentication" and msg["Authentication"]["status"] == "NT_STATUS_WRONG_PASSWORD" and msg["Authentication"]["serviceDescription"] == "SAMR Password Change" and msg["Authentication"]["authDescription"] == "samr_ChangePasswordUser3") creds = self.insta_creds(template=self.get_credentials()) lp = self.get_loadparm() net = Net(creds, lp, server=self.server_ip) password = "******" exception_thrown = False try: net.change_password(newpassword=password.encode('utf-8'), oldpassword="******", username=USER_NAME) except Exception, msg: exception_thrown = True
def test_net_change_password(self): dn = "CN=" + USER_NAME + ",CN=Users," + self.base_dn self.discardSetupMessages(dn) creds = self.insta_creds(template=self.get_credentials()) lp = self.get_loadparm() net = Net(creds, lp, server=self.server) password = "******" net.change_password(newpassword=password.encode('utf-8'), username=USER_NAME, oldpassword=USER_PASS) messages = self.waitForMessages(1, net, dn=dn) print("Received %d messages" % len(messages)) self.assertEquals(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["dsdbChange"] self.assertEquals("Modify", audit["operation"]) self.assertFalse(audit["performedAsSystem"]) self.assertTrue(dn.lower(), audit["dn"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "DCE/RPC") self.assertTrue(self.is_guid(audit["transactionId"])) attributes = audit["attributes"] self.assertEquals(1, len(attributes)) actions = attributes["clearTextPassword"]["actions"] self.assertEquals(1, len(actions)) self.assertTrue(actions[0]["redacted"]) self.assertEquals("replace", actions[0]["action"])
def test_net_set_password(self): dn = "CN=" + USER_NAME + ",CN=Users," + self.base_dn self.discardSetupMessages(dn) creds = self.insta_creds(template=self.get_credentials()) lp = self.get_loadparm() net = Net(creds, lp, server=self.server) password = "******" domain = lp.get("workgroup") net.set_password(newpassword=password, account_name=USER_NAME, domain_name=domain) dn = "CN=" + USER_NAME + ",CN=Users," + self.base_dn messages = self.waitForMessages(1, net, dn) print("Received %d messages" % len(messages)) self.assertEquals(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["passwordChange"] self.assertEquals(EVT_ID_PASSWORD_RESET, audit["eventId"]) self.assertEquals("Reset", audit["action"]) self.assertEquals(dn, audit["dn"]) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEquals(service_description, "DCE/RPC") session_id = self.get_session() self.assertEquals(session_id, audit["sessionId"]) self.assertTrue(self.is_guid(audit["transactionId"]))
def test_net_join_no_spnego(self): self.lp.set("client use spnego", "no") netbios_name = "NetJoinNoSpnego" machinepass = "******" creds = self.insta_creds(template=self.get_credentials(), kerberos_state=DONT_USE_KERBEROS) net = Net(creds, self.lp, server=self.server) try: (join_password, sid, domain_name) = net.join_member(self.domain, netbios_name, LIBNET_JOIN_AUTOMATIC, machinepass=machinepass) except NTSTATUSError as e: code = ctypes.c_uint32(e.args[0]).value if code == ntstatus.NT_STATUS_CONNECTION_DISCONNECTED: self.fail("Connection failure") elif code == ntstatus.NT_STATUS_ACCESS_DENIED: return else: raise self.fail("Shoud have rejected NTLMv2 without SPNEGO")
def test_admin_change_password(self): def isLastExpectedMessage(msg): return ((msg["type"] == "Authentication") and (msg["Authentication"]["status"] == "NT_STATUS_OK") and (msg["Authentication"]["serviceDescription"] == "SAMR Password Change") and (msg["Authentication"]["authDescription"] == "samr_ChangePasswordUser3")) creds = self.insta_creds(template=self.get_credentials()) lp = self.get_loadparm() net = Net(creds, lp, server=self.server_ip) password = "******" net.change_password(newpassword=password.encode('utf-8'), username=USER_NAME, oldpassword=USER_PASS) messages = self.waitForMessages(isLastExpectedMessage) print("Received %d messages" % len(messages)) self.assertEquals(8, len(messages), "Did not receive the expected number of messages")
def test_net_join(self): netbios_name = "NetJoinTest" machinepass = "******" creds = self.insta_creds(template=self.get_credentials(), kerberos_state=DONT_USE_KERBEROS) net = Net(creds, self.lp, server=self.server) # NOTE WELL: We must not run more than one successful # net.join_member per file (process), as the shared # secrets.ldb handle will be kept between runs. try: (join_password, sid, domain_name) = net.join_member(self.domain, netbios_name, LIBNET_JOIN_AUTOMATIC, machinepass=machinepass) except NTSTATUSError as e: code = ctypes.c_uint32(e.args[0]).value if code == ntstatus.NT_STATUS_CONNECTION_DISCONNECTED: self.fail("Connection failure") raise os.unlink(os.path.join(self.tempdir, "secrets.ldb")) pass
def run(self, name, password=None, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) net = Net(creds, lp, server=credopts.ipaddress) net.create_user(name) if password is not None: net.set_password(name, creds.get_domain(), password, creds)
def test_net_replicate_init__1(self): lp, creds, server = self.get_lp_et_al() net = Net(creds, lp, server=server) net.replicate_init(42, lp, None, misc.GUID())
def __init__(self, username, password): BaseModel.__init__(self, username, password) self.user_list = [] if self.isAuthenticate(): self.net = Net(self.creds, self.lp, server=self.server_address) self.LoadUserList()
def test_net_set_password_user_without_permission(self): dn = "CN=" + USER_NAME + ",CN=Users," + self.base_dn self.discardSetupMessages(dn) self.ldb.newuser(SECOND_USER_NAME, SECOND_USER_PASS) # # Get the password reset from the user add # dn = "CN=" + SECOND_USER_NAME + ",CN=Users," + self.base_dn messages = self.waitForMessages(1, dn=dn) print("Received %d messages" % len(messages)) self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["passwordChange"] self.assertEqual(EVT_ID_PASSWORD_RESET, audit["eventId"]) self.assertEqual("Reset", audit["action"]) self.assertEqual(dn, audit["dn"]) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) session_id = self.get_session() self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEqual(service_description, "LDAP") self.assertTrue(self.is_guid(audit["transactionId"])) self.assertEqual(0, audit["statusCode"]) self.assertEqual("Success", audit["status"]) self.discardMessages() creds = self.insta_creds(template=self.get_credentials(), username=SECOND_USER_NAME, userpass=SECOND_USER_PASS, kerberos_state=None) lp = self.get_loadparm() net = Net(creds, lp, server=self.server) password = "******" domain = lp.get("workgroup") try: net.set_password(newpassword=password, account_name=USER_NAME, domain_name=domain) self.fail("Expected exception not thrown") except Exception: pass dn = "CN=" + USER_NAME + ",CN=Users," + self.base_dn messages = self.waitForMessages(1, net, dn=dn) print("Received %d messages" % len(messages)) self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["passwordChange"] self.assertEqual(EVT_ID_PASSWORD_RESET, audit["eventId"]) self.assertEqual("Reset", audit["action"]) self.assertEqual(dn, audit["dn"]) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) session_id = self.get_session() self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() self.assertEqual(service_description, "DCE/RPC") self.assertTrue(self.is_guid(audit["transactionId"])) self.assertEqual(ERR_INSUFFICIENT_ACCESS_RIGHTS, audit["statusCode"]) self.assertEqual("insufficient access rights", audit["status"])
def get_dc_hostname(creds, lp): net = Net(creds=creds, lp=lp) cldap_ret = net.finddc(domain=lp.get('realm'), flags=(nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS)) return cldap_ret.pdc_dns_name
class drs_Replicate(object): '''DRS replication calls''' def __init__(self, binding_string, lp, creds, samdb, invocation_id): self.drs = drsuapi.drsuapi(binding_string, lp, creds) (self.drs_handle, self.supported_extensions) = drs_DsBind(self.drs) self.net = Net(creds=creds, lp=lp) self.samdb = samdb if not isinstance(invocation_id, misc.GUID): raise RuntimeError("Must supply GUID for invocation_id") if invocation_id == misc.GUID("00000000-0000-0000-0000-000000000000"): raise RuntimeError( "Must not set GUID 00000000-0000-0000-0000-000000000000 as invocation_id" ) self.replication_state = self.net.replicate_init( self.samdb, lp, self.drs, invocation_id) def drs_get_rodc_partial_attribute_set(self): '''get a list of attributes for RODC replication''' partial_attribute_set = drsuapi.DsPartialAttributeSet() partial_attribute_set.version = 1 attids = [] # the exact list of attids we send is quite critical. Note that # we do ask for the secret attributes, but set SPECIAL_SECRET_PROCESSING # to zero them out schema_dn = self.samdb.get_schema_basedn() res = self.samdb.search( base=schema_dn, scope=ldb.SCOPE_SUBTREE, expression="objectClass=attributeSchema", attrs=["lDAPDisplayName", "systemFlags", "searchFlags"]) for r in res: ldap_display_name = r["lDAPDisplayName"][0] if "systemFlags" in r: system_flags = r["systemFlags"][0] if (int(system_flags) & (samba.dsdb.DS_FLAG_ATTR_NOT_REPLICATED | samba.dsdb.DS_FLAG_ATTR_IS_CONSTRUCTED)): continue if "searchFlags" in r: search_flags = r["searchFlags"][0] if (int(search_flags) & samba.dsdb.SEARCH_FLAG_RODC_ATTRIBUTE): continue attid = self.samdb.get_attid_from_lDAPDisplayName( ldap_display_name) attids.append(int(attid)) # the attids do need to be sorted, or windows doesn't return # all the attributes we need attids.sort() partial_attribute_set.attids = attids partial_attribute_set.num_attids = len(attids) return partial_attribute_set def replicate(self, dn, source_dsa_invocation_id, destination_dsa_guid, schema=False, exop=drsuapi.DRSUAPI_EXOP_NONE, rodc=False, replica_flags=None): '''replicate a single DN''' # setup for a GetNCChanges call req8 = drsuapi.DsGetNCChangesRequest8() req8.destination_dsa_guid = destination_dsa_guid req8.source_dsa_invocation_id = source_dsa_invocation_id req8.naming_context = drsuapi.DsReplicaObjectIdentifier() req8.naming_context.dn = dn req8.highwatermark = drsuapi.DsReplicaHighWaterMark() req8.highwatermark.tmp_highest_usn = 0 req8.highwatermark.reserved_usn = 0 req8.highwatermark.highest_usn = 0 req8.uptodateness_vector = None if replica_flags is not None: req8.replica_flags = replica_flags elif exop == drsuapi.DRSUAPI_EXOP_REPL_SECRET: req8.replica_flags = 0 else: req8.replica_flags = (drsuapi.DRSUAPI_DRS_INIT_SYNC | drsuapi.DRSUAPI_DRS_PER_SYNC | drsuapi.DRSUAPI_DRS_GET_ANC | drsuapi.DRSUAPI_DRS_NEVER_SYNCED | drsuapi.DRSUAPI_DRS_GET_ALL_GROUP_MEMBERSHIP) if rodc: req8.replica_flags |= ( drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING) else: req8.replica_flags |= drsuapi.DRSUAPI_DRS_WRIT_REP req8.max_object_count = 402 req8.max_ndr_size = 402116 req8.extended_op = exop req8.fsmo_info = 0 req8.partial_attribute_set = None req8.partial_attribute_set_ex = None req8.mapping_ctr.num_mappings = 0 req8.mapping_ctr.mappings = None if not schema and rodc: req8.partial_attribute_set = self.drs_get_rodc_partial_attribute_set( ) if self.supported_extensions & drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8: req_level = 8 req = req8 else: req_level = 5 req5 = drsuapi.DsGetNCChangesRequest5() for a in dir(req5): if a[0] != '_': setattr(req5, a, getattr(req8, a)) req = req5 while True: (level, ctr) = self.drs.DsGetNCChanges(self.drs_handle, req_level, req) if ctr.first_object is None and ctr.object_count != 0: raise RuntimeError( "DsGetNCChanges: NULL first_object with object_count=%u" % (ctr.object_count)) self.net.replicate_chunk(self.replication_state, level, ctr, schema=schema, req_level=req_level, req=req) if ctr.more_data == 0: break req.highwatermark = ctr.new_highwatermark
class drs_Replicate(object): '''DRS replication calls''' def __init__(self, binding_string, lp, creds, samdb, invocation_id): self.drs = drsuapi.drsuapi(binding_string, lp, creds) (self.drs_handle, self.supported_extensions) = drs_DsBind(self.drs) self.net = Net(creds=creds, lp=lp) self.samdb = samdb if not isinstance(invocation_id, misc.GUID): raise RuntimeError("Must supply GUID for invocation_id") if invocation_id == misc.GUID("00000000-0000-0000-0000-000000000000"): raise RuntimeError( "Must not set GUID 00000000-0000-0000-0000-000000000000 as invocation_id" ) self.replication_state = self.net.replicate_init( self.samdb, lp, self.drs, invocation_id) def replicate(self, dn, source_dsa_invocation_id, destination_dsa_guid, schema=False, exop=drsuapi.DRSUAPI_EXOP_NONE, rodc=False, replica_flags=None, full_sync=True, sync_forced=False): '''replicate a single DN''' # setup for a GetNCChanges call req8 = drsuapi.DsGetNCChangesRequest8() req8.destination_dsa_guid = destination_dsa_guid req8.source_dsa_invocation_id = source_dsa_invocation_id req8.naming_context = drsuapi.DsReplicaObjectIdentifier() req8.naming_context.dn = dn # Default to a full replication if we don't find an upToDatenessVector udv = None hwm = drsuapi.DsReplicaHighWaterMark() hwm.tmp_highest_usn = 0 hwm.reserved_usn = 0 hwm.highest_usn = 0 if not full_sync: res = self.samdb.search(base=dn, scope=ldb.SCOPE_BASE, attrs=["repsFrom"]) if "repsFrom" in res[0]: for reps_from_packed in res[0]["repsFrom"]: reps_from_obj = ndr_unpack(drsblobs.repsFromToBlob, reps_from_packed) if reps_from_obj.ctr.source_dsa_invocation_id == source_dsa_invocation_id: hwm = reps_from_obj.ctr.highwatermark udv = drsuapi.DsReplicaCursorCtrEx() udv.version = 1 udv.reserved1 = 0 udv.reserved2 = 0 cursors_v1 = [] cursors_v2 = dsdb._dsdb_load_udv_v2( self.samdb, self.samdb.get_default_basedn()) for cursor_v2 in cursors_v2: cursor_v1 = drsuapi.DsReplicaCursor() cursor_v1.source_dsa_invocation_id = cursor_v2.source_dsa_invocation_id cursor_v1.highest_usn = cursor_v2.highest_usn cursors_v1.append(cursor_v1) udv.cursors = cursors_v1 udv.count = len(cursors_v1) req8.highwatermark = hwm req8.uptodateness_vector = udv if replica_flags is not None: req8.replica_flags = replica_flags elif exop == drsuapi.DRSUAPI_EXOP_REPL_SECRET: req8.replica_flags = 0 else: req8.replica_flags = (drsuapi.DRSUAPI_DRS_INIT_SYNC | drsuapi.DRSUAPI_DRS_PER_SYNC | drsuapi.DRSUAPI_DRS_GET_ANC | drsuapi.DRSUAPI_DRS_NEVER_SYNCED | drsuapi.DRSUAPI_DRS_GET_ALL_GROUP_MEMBERSHIP) if rodc: req8.replica_flags |= ( drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING) else: req8.replica_flags |= drsuapi.DRSUAPI_DRS_WRIT_REP if sync_forced: req8.replica_flags |= drsuapi.DRSUAPI_DRS_SYNC_FORCED req8.max_object_count = 402 req8.max_ndr_size = 402116 req8.extended_op = exop req8.fsmo_info = 0 req8.partial_attribute_set = None req8.partial_attribute_set_ex = None req8.mapping_ctr.num_mappings = 0 req8.mapping_ctr.mappings = None if not schema and rodc: req8.partial_attribute_set = drs_get_rodc_partial_attribute_set( self.samdb) if self.supported_extensions & drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8: req_level = 8 req = req8 else: req_level = 5 req5 = drsuapi.DsGetNCChangesRequest5() for a in dir(req5): if a[0] != '_': setattr(req5, a, getattr(req8, a)) req = req5 num_objects = 0 num_links = 0 while True: (level, ctr) = self.drs.DsGetNCChanges(self.drs_handle, req_level, req) if ctr.first_object is None and ctr.object_count != 0: raise RuntimeError( "DsGetNCChanges: NULL first_object with object_count=%u" % (ctr.object_count)) self.net.replicate_chunk(self.replication_state, level, ctr, schema=schema, req_level=req_level, req=req) num_objects += ctr.object_count # Cope with servers that do not return level 6, so do not return any links try: num_links += ctr.linked_attributes_count except AttributeError: pass if ctr.more_data == 0: break req.highwatermark = ctr.new_highwatermark return (num_objects, num_links)
def __init__(ctx, server=None, creds=None, lp=None, site=None, netbios_name=None, targetdir=None, domain=None): ctx.creds = creds ctx.lp = lp ctx.site = site ctx.netbios_name = netbios_name ctx.targetdir = targetdir ctx.creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL) ctx.net = Net(creds=ctx.creds, lp=ctx.lp) if server is not None: ctx.server = server else: print("Finding a writeable DC for domain '%s'" % domain) ctx.server = ctx.find_dc(domain) print("Found DC %s" % ctx.server) ctx.samdb = SamDB(url="ldap://%s" % ctx.server, session_info=system_session(), credentials=ctx.creds, lp=ctx.lp) ctx.myname = netbios_name ctx.samname = "%s$" % ctx.myname ctx.base_dn = str(ctx.samdb.get_default_basedn()) ctx.root_dn = str(ctx.samdb.get_root_basedn()) ctx.schema_dn = str(ctx.samdb.get_schema_basedn()) ctx.config_dn = str(ctx.samdb.get_config_basedn()) ctx.domsid = ctx.samdb.get_domain_sid() ctx.domain_name = ctx.get_domain_name() lp.set("workgroup", ctx.domain_name) print("workgroup is %s" % ctx.domain_name) ctx.dc_ntds_dn = ctx.get_dsServiceName() ctx.dc_dnsHostName = ctx.get_dnsHostName() ctx.behavior_version = ctx.get_behavior_version() ctx.acct_pass = samba.generate_random_password(32, 40) # work out the DNs of all the objects we will be adding ctx.server_dn = "CN=%s,CN=Servers,CN=%s,CN=Sites,%s" % (ctx.myname, ctx.site, ctx.config_dn) ctx.ntds_dn = "CN=NTDS Settings,%s" % ctx.server_dn topology_base = "CN=Topology,CN=Domain System Volume,CN=DFSR-GlobalSettings,CN=System,%s" % ctx.base_dn if ctx.dn_exists(topology_base): ctx.topology_dn = "CN=%s,%s" % (ctx.myname, topology_base) else: ctx.topology_dn = None ctx.dnsdomain = ldb.Dn(ctx.samdb, ctx.base_dn).canonical_str().split('/')[0] ctx.realm = ctx.dnsdomain lp.set("realm", ctx.realm) print("realm is %s" % ctx.realm) ctx.dnshostname = "%s.%s" % (ctx.myname.lower(), ctx.dnsdomain) ctx.acct_dn = "CN=%s,OU=Domain Controllers,%s" % (ctx.myname, ctx.base_dn) ctx.tmp_samdb = None ctx.SPNs = [ "HOST/%s" % ctx.myname, "HOST/%s" % ctx.dnshostname, "GC/%s/%s" % (ctx.dnshostname, ctx.dnsdomain) ] # these elements are optional ctx.never_reveal_sid = None ctx.reveal_sid = None ctx.connection_dn = None ctx.RODC = False ctx.krbtgt_dn = None ctx.drsuapi = None ctx.managedby = None
class drs_Replicate(object): '''DRS replication calls''' def __init__(self, binding_string, lp, creds, samdb, invocation_id): self.drs = drsuapi.drsuapi(binding_string, lp, creds) (self.drs_handle, self.supported_extensions) = drs_DsBind(self.drs) self.net = Net(creds=creds, lp=lp) self.samdb = samdb if not isinstance(invocation_id, misc.GUID): raise RuntimeError("Must supply GUID for invocation_id") if invocation_id == misc.GUID("00000000-0000-0000-0000-000000000000"): raise RuntimeError("Must not set GUID 00000000-0000-0000-0000-000000000000 as invocation_id") self.replication_state = self.net.replicate_init(self.samdb, lp, self.drs, invocation_id) def replicate(self, dn, source_dsa_invocation_id, destination_dsa_guid, schema=False, exop=drsuapi.DRSUAPI_EXOP_NONE, rodc=False, replica_flags=None, full_sync=True): '''replicate a single DN''' # setup for a GetNCChanges call req8 = drsuapi.DsGetNCChangesRequest8() req8.destination_dsa_guid = destination_dsa_guid req8.source_dsa_invocation_id = source_dsa_invocation_id req8.naming_context = drsuapi.DsReplicaObjectIdentifier() req8.naming_context.dn = dn udv = None if not full_sync: res = self.samdb.search(base=dn, scope=ldb.SCOPE_BASE, attrs=["repsFrom"]) if "repsFrom" in res[0]: for reps_from_packed in res[0]["repsFrom"]: reps_from_obj = ndr_unpack(drsblobs.repsFromToBlob, reps_from_packed) if reps_from_obj.ctr.source_dsa_invocation_id == source_dsa_invocation_id: hwm = reps_from_obj.ctr.highwatermark udv = drsuapi.DsReplicaCursorCtrEx() udv.version = 1 udv.reserved1 = 0 udv.reserved2 = 0 cursors_v1 = [] cursors_v2 = dsdb._dsdb_load_udv_v2(self.samdb, self.samdb.get_default_basedn()) for cursor_v2 in cursors_v2: cursor_v1 = drsuapi.DsReplicaCursor() cursor_v1.source_dsa_invocation_id = cursor_v2.source_dsa_invocation_id cursor_v1.highest_usn = cursor_v2.highest_usn cursors_v1.append(cursor_v1) udv.cursors = cursors_v1 udv.count = len(cursors_v1) # If we can't find an upToDateVector, or where told not to, replicate fully hwm = drsuapi.DsReplicaHighWaterMark() hwm.tmp_highest_usn = 0 hwm.reserved_usn = 0 hwm.highest_usn = 0 req8.highwatermark = hwm req8.uptodateness_vector = udv if replica_flags is not None: req8.replica_flags = replica_flags elif exop == drsuapi.DRSUAPI_EXOP_REPL_SECRET: req8.replica_flags = 0 else: req8.replica_flags = (drsuapi.DRSUAPI_DRS_INIT_SYNC | drsuapi.DRSUAPI_DRS_PER_SYNC | drsuapi.DRSUAPI_DRS_GET_ANC | drsuapi.DRSUAPI_DRS_NEVER_SYNCED | drsuapi.DRSUAPI_DRS_GET_ALL_GROUP_MEMBERSHIP) if rodc: req8.replica_flags |= ( drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING) else: req8.replica_flags |= drsuapi.DRSUAPI_DRS_WRIT_REP req8.max_object_count = 402 req8.max_ndr_size = 402116 req8.extended_op = exop req8.fsmo_info = 0 req8.partial_attribute_set = None req8.partial_attribute_set_ex = None req8.mapping_ctr.num_mappings = 0 req8.mapping_ctr.mappings = None if not schema and rodc: req8.partial_attribute_set = drs_get_rodc_partial_attribute_set(self.samdb) if self.supported_extensions & drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8: req_level = 8 req = req8 else: req_level = 5 req5 = drsuapi.DsGetNCChangesRequest5() for a in dir(req5): if a[0] != '_': setattr(req5, a, getattr(req8, a)) req = req5 num_objects = 0 num_links = 0 while True: (level, ctr) = self.drs.DsGetNCChanges(self.drs_handle, req_level, req) if ctr.first_object is None and ctr.object_count != 0: raise RuntimeError("DsGetNCChanges: NULL first_object with object_count=%u" % (ctr.object_count)) self.net.replicate_chunk(self.replication_state, level, ctr, schema=schema, req_level=req_level, req=req) num_objects += ctr.object_count # Cope with servers that do not return level 6, so do not return any links try: num_links += ctr.linked_attributes_count except AttributeError: pass if ctr.more_data == 0: break req.highwatermark = ctr.new_highwatermark return (num_objects, num_links)
def run(self, keytab, credopts=None, sambaopts=None, versionopts=None, principal=None): lp = sambaopts.get_loadparm() net = Net(None, lp) net.export_keytab(keytab=keytab, principal=principal)
def net_lookup(domain): global cldap_ret net = Net(Credentials()) cldap_ret = net.finddc(domain=domain, flags=(nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS))
class drs_Replicate(object): '''DRS replication calls''' def __init__(self, binding_string, lp, creds, samdb, invocation_id): self.drs = drsuapi.drsuapi(binding_string, lp, creds) (self.drs_handle, self.supported_extensions) = drs_DsBind(self.drs) self.net = Net(creds=creds, lp=lp) self.samdb = samdb if not isinstance(invocation_id, misc.GUID): raise RuntimeError("Must supply GUID for invocation_id") if invocation_id == misc.GUID("00000000-0000-0000-0000-000000000000"): raise RuntimeError( "Must not set GUID 00000000-0000-0000-0000-000000000000 as invocation_id" ) self.replication_state = self.net.replicate_init( self.samdb, lp, self.drs, invocation_id) def replicate(self, dn, source_dsa_invocation_id, destination_dsa_guid, schema=False, exop=drsuapi.DRSUAPI_EXOP_NONE, rodc=False, replica_flags=None, highwatermark=None, udv=None): '''replicate a single DN''' # setup for a GetNCChanges call req8 = drsuapi.DsGetNCChangesRequest8() req8.destination_dsa_guid = destination_dsa_guid req8.source_dsa_invocation_id = source_dsa_invocation_id req8.naming_context = drsuapi.DsReplicaObjectIdentifier() req8.naming_context.dn = dn if highwatermark is not None: req8.highwatermark = highwatermark else: req8.highwatermark = drsuapi.DsReplicaHighWaterMark() req8.highwatermark.tmp_highest_usn = 0 req8.highwatermark.reserved_usn = 0 req8.highwatermark.highest_usn = 0 req8.uptodateness_vector = udv if replica_flags is not None: req8.replica_flags = replica_flags elif exop == drsuapi.DRSUAPI_EXOP_REPL_SECRET: req8.replica_flags = 0 else: req8.replica_flags = (drsuapi.DRSUAPI_DRS_INIT_SYNC | drsuapi.DRSUAPI_DRS_PER_SYNC | drsuapi.DRSUAPI_DRS_GET_ANC | drsuapi.DRSUAPI_DRS_NEVER_SYNCED | drsuapi.DRSUAPI_DRS_GET_ALL_GROUP_MEMBERSHIP) if rodc: req8.replica_flags |= ( drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING) else: req8.replica_flags |= drsuapi.DRSUAPI_DRS_WRIT_REP req8.max_object_count = 402 req8.max_ndr_size = 402116 req8.extended_op = exop req8.fsmo_info = 0 req8.partial_attribute_set = None req8.partial_attribute_set_ex = None req8.mapping_ctr.num_mappings = 0 req8.mapping_ctr.mappings = None if not schema and rodc: req8.partial_attribute_set = drs_get_rodc_partial_attribute_set( self.samdb) if self.supported_extensions & drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8: req_level = 8 req = req8 else: req_level = 5 req5 = drsuapi.DsGetNCChangesRequest5() for a in dir(req5): if a[0] != '_': setattr(req5, a, getattr(req8, a)) req = req5 num_objects = 0 num_links = 0 while True: (level, ctr) = self.drs.DsGetNCChanges(self.drs_handle, req_level, req) if ctr.first_object is None and ctr.object_count != 0: raise RuntimeError( "DsGetNCChanges: NULL first_object with object_count=%u" % (ctr.object_count)) self.net.replicate_chunk(self.replication_state, level, ctr, schema=schema, req_level=req_level, req=req) num_objects += ctr.object_count # Cope with servers that do not return level 6, so do not return any links try: num_links += ctr.linked_attributes_count except AttributeError: pass if ctr.more_data == 0: break req.highwatermark = ctr.new_highwatermark return (num_objects, num_links)
def run(self, displayname, H=None, tmpdir=None, sambaopts=None, credopts=None, versionopts=None): self.lp = sambaopts.get_loadparm() self.creds = credopts.get_credentials(self.lp, fallback_machine=True) net = Net(creds=self.creds, lp=self.lp) # We need to know writable DC to setup SMB connection if H and H.startswith('ldap://'): dc_hostname = H[7:] self.url = H flags = (nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE) cldap_ret = net.finddc(address=dc_hostname, flags=flags) else: flags = (nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE) cldap_ret = net.finddc(domain=self.lp.get('realm'), flags=flags) dc_hostname = cldap_ret.pdc_dns_name self.url = dc_url(self.lp, self.creds, dc=dc_hostname) samdb_connect(self) msg = get_gpo_info(self.samdb, displayname=displayname) if msg.count > 0: raise CommandError("A GPO already existing with name '%s'" % displayname) # Create new GUID guid = str(uuid.uuid4()) gpo = "{%s}" % guid.upper() realm = cldap_ret.dns_domain unc_path = "\\\\%s\\sysvol\\%s\\Policies\\%s" % (realm, realm, gpo) # Create GPT if tmpdir is None: tmpdir = "/tmp" if not os.path.isdir(tmpdir): raise CommandError("Temporary directory '%s' does not exist" % tmpdir) localdir = os.path.join(tmpdir, "policy") if not os.path.isdir(localdir): os.mkdir(localdir) gpodir = os.path.join(localdir, gpo) if os.path.isdir(gpodir): raise CommandError( "GPO directory '%s' already exists, refusing to overwrite" % gpodir) try: os.mkdir(gpodir) os.mkdir(os.path.join(gpodir, "Machine")) os.mkdir(os.path.join(gpodir, "User")) gpt_contents = "[General]\r\nVersion=0\r\n" file(os.path.join(gpodir, "GPT.INI"), "w").write(gpt_contents) except Exception, e: raise CommandError("Error Creating GPO files", e)
def __init__(self, binding_string, lp, creds, samdb): self.drs = drsuapi.drsuapi(binding_string, lp, creds) (self.drs_handle, self.supported_extensions) = drs_DsBind(self.drs) self.net = Net(creds=creds, lp=lp) self.samdb = samdb self.replication_state = self.net.replicate_init(self.samdb, lp, self.drs)
parser.add_option('-S', '--sAMAccountName', action='store', dest='name', help='The sAMAccountName of the object to manipulate') (opts, args) = parser.parse_args() if opts.__dict__['name'] is None: parser.error('Parameter --sAMAccountName is required') lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) realm = lp.get('realm') net = Net(creds) cldap_ret = net.finddc(domain=realm, flags=(nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE)) host = cldap_ret.pdc_dns_name ldb = samdb.SamDB(url='ldap://%s' % host, lp=lp, credentials=creds, session_info=system_session()) domain_sid = security.dom_sid(ldb.get_domain_sid()) s = samr.samr("ncacn_ip_tcp:%s[seal]" % host, lp, creds) samr_handle = s.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED) samr_domain = s.OpenDomain(samr_handle, security.SEC_FLAG_MAXIMUM_ALLOWED, domain_sid)
def test_net_replicate_init__3(self): # third argument is also unchecked samdb = self.get_samdb() lp, creds, server = self.get_lp_et_al() net = Net(creds, lp, server=server) net.replicate_init(samdb, lp, 42, misc.GUID())
def test_net_replicate_chunk_1(self): lp, creds, server = self.get_lp_et_al() ctr = drsuapi.DsGetNCChangesCtr6() net = Net(creds, lp, server=server) net.replicate_chunk(42, 1, ctr)
def run(self, displayname, H=None, tmpdir=None, sambaopts=None, credopts=None, versionopts=None): self.lp = sambaopts.get_loadparm() self.creds = credopts.get_credentials(self.lp, fallback_machine=True) net = Net(creds=self.creds, lp=self.lp) # We need to know writable DC to setup SMB connection if H and H.startswith('ldap://'): dc_hostname = H[7:] self.url = H flags = (nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE) cldap_ret = net.finddc(address=dc_hostname, flags=flags) else: flags = (nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE) cldap_ret = net.finddc(domain=self.lp.get('realm'), flags=flags) dc_hostname = cldap_ret.pdc_dns_name self.url = dc_url(self.lp, self.creds, dc=dc_hostname) samdb_connect(self) msg = get_gpo_info(self.samdb, displayname=displayname) if msg.count > 0: raise CommandError("A GPO already existing with name '%s'" % displayname) # Create new GUID guid = str(uuid.uuid4()) gpo = "{%s}" % guid.upper() realm = cldap_ret.dns_domain unc_path = "\\\\%s\\sysvol\\%s\\Policies\\%s" % (realm, realm, gpo) # Create GPT if tmpdir is None: tmpdir = "/tmp" if not os.path.isdir(tmpdir): raise CommandError("Temporary directory '%s' does not exist" % tmpdir) localdir = os.path.join(tmpdir, "policy") if not os.path.isdir(localdir): os.mkdir(localdir) gpodir = os.path.join(localdir, gpo) if os.path.isdir(gpodir): raise CommandError("GPO directory '%s' already exists, refusing to overwrite" % gpodir) try: os.mkdir(gpodir) os.mkdir(os.path.join(gpodir, "Machine")) os.mkdir(os.path.join(gpodir, "User")) gpt_contents = "[General]\r\nVersion=0\r\n" open(os.path.join(gpodir, "GPT.INI"), "w").write(gpt_contents) except Exception as e: raise CommandError("Error Creating GPO files", e) # Connect to DC over SMB [dom_name, service, sharepath] = parse_unc(unc_path) try: conn = smb.SMB(dc_hostname, service, lp=self.lp, creds=self.creds) except Exception as e: raise CommandError("Error connecting to '%s' using SMB" % dc_hostname, e) self.samdb.transaction_start() try: # Add cn=<guid> gpo_dn = get_gpo_dn(self.samdb, gpo) m = ldb.Message() m.dn = gpo_dn m['a01'] = ldb.MessageElement("groupPolicyContainer", ldb.FLAG_MOD_ADD, "objectClass") self.samdb.add(m) # Add cn=User,cn=<guid> m = ldb.Message() m.dn = ldb.Dn(self.samdb, "CN=User,%s" % str(gpo_dn)) m['a01'] = ldb.MessageElement("container", ldb.FLAG_MOD_ADD, "objectClass") self.samdb.add(m) # Add cn=Machine,cn=<guid> m = ldb.Message() m.dn = ldb.Dn(self.samdb, "CN=Machine,%s" % str(gpo_dn)) m['a01'] = ldb.MessageElement("container", ldb.FLAG_MOD_ADD, "objectClass") self.samdb.add(m) # Get new security descriptor ds_sd_flags = ( security.SECINFO_OWNER | security.SECINFO_GROUP | security.SECINFO_DACL ) msg = get_gpo_info(self.samdb, gpo=gpo, sd_flags=ds_sd_flags)[0] ds_sd_ndr = msg['nTSecurityDescriptor'][0] ds_sd = ndr_unpack(security.descriptor, ds_sd_ndr).as_sddl() # Create a file system security descriptor domain_sid = security.dom_sid(self.samdb.get_domain_sid()) sddl = dsacl2fsacl(ds_sd, domain_sid) fs_sd = security.descriptor.from_sddl(sddl, domain_sid) # Copy GPO directory create_directory_hier(conn, sharepath) # Set ACL sio = ( security.SECINFO_OWNER | security.SECINFO_GROUP | security.SECINFO_DACL | security.SECINFO_PROTECTED_DACL ) conn.set_acl(sharepath, fs_sd, sio) # Copy GPO files over SMB copy_directory_local_to_remote(conn, gpodir, sharepath) m = ldb.Message() m.dn = gpo_dn m['a02'] = ldb.MessageElement(displayname, ldb.FLAG_MOD_REPLACE, "displayName") m['a03'] = ldb.MessageElement(unc_path, ldb.FLAG_MOD_REPLACE, "gPCFileSysPath") m['a05'] = ldb.MessageElement("0", ldb.FLAG_MOD_REPLACE, "versionNumber") m['a07'] = ldb.MessageElement("2", ldb.FLAG_MOD_REPLACE, "gpcFunctionalityVersion") m['a04'] = ldb.MessageElement("0", ldb.FLAG_MOD_REPLACE, "flags") controls=["permissive_modify:0"] self.samdb.modify(m, controls=controls) except Exception: self.samdb.transaction_cancel() raise else: self.samdb.transaction_commit() self.outf.write("GPO '%s' created as %s\n" % (displayname, gpo))
def run(self, displayname, H=None, tmpdir=None, sambaopts=None, credopts=None, versionopts=None): self.lp = sambaopts.get_loadparm() self.creds = credopts.get_credentials(self.lp, fallback_machine=True) net = Net(creds=self.creds, lp=self.lp) # We need to know writable DC to setup SMB connection if H and H.startswith('ldap://'): dc_hostname = H[7:] self.url = H flags = (nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE) cldap_ret = net.finddc(address=dc_hostname, flags=flags) else: flags = (nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE) cldap_ret = net.finddc(domain=self.lp.get('realm'), flags=flags) dc_hostname = cldap_ret.pdc_dns_name self.url = dc_url(self.lp, self.creds, dc=dc_hostname) samdb_connect(self) msg = get_gpo_info(self.samdb, displayname=displayname) if msg.count > 0: raise CommandError("A GPO already existing with name '%s'" % displayname) # Create new GUID guid = str(uuid.uuid4()) gpo = "{%s}" % guid.upper() realm = cldap_ret.dns_domain unc_path = "\\\\%s\\sysvol\\%s\\Policies\\%s" % (realm, realm, gpo) # Create GPT if tmpdir is None: tmpdir = "/tmp" if not os.path.isdir(tmpdir): raise CommandError("Temporary directory '%s' does not exist" % tmpdir) localdir = os.path.join(tmpdir, "policy") if not os.path.isdir(localdir): os.mkdir(localdir) gpodir = os.path.join(localdir, gpo) if os.path.isdir(gpodir): raise CommandError( "GPO directory '%s' already exists, refusing to overwrite" % gpodir) try: os.mkdir(gpodir) os.mkdir(os.path.join(gpodir, "Machine")) os.mkdir(os.path.join(gpodir, "User")) gpt_contents = "[General]\r\nVersion=0\r\n" open(os.path.join(gpodir, "GPT.INI"), "w").write(gpt_contents) except Exception as e: raise CommandError("Error Creating GPO files", e) # Connect to DC over SMB [dom_name, service, sharepath] = parse_unc(unc_path) try: conn = smb.SMB(dc_hostname, service, lp=self.lp, creds=self.creds) except Exception as e: raise CommandError( "Error connecting to '%s' using SMB" % dc_hostname, e) self.samdb.transaction_start() try: # Add cn=<guid> gpo_dn = get_gpo_dn(self.samdb, gpo) m = ldb.Message() m.dn = gpo_dn m['a01'] = ldb.MessageElement("groupPolicyContainer", ldb.FLAG_MOD_ADD, "objectClass") self.samdb.add(m) # Add cn=User,cn=<guid> m = ldb.Message() m.dn = ldb.Dn(self.samdb, "CN=User,%s" % str(gpo_dn)) m['a01'] = ldb.MessageElement("container", ldb.FLAG_MOD_ADD, "objectClass") self.samdb.add(m) # Add cn=Machine,cn=<guid> m = ldb.Message() m.dn = ldb.Dn(self.samdb, "CN=Machine,%s" % str(gpo_dn)) m['a01'] = ldb.MessageElement("container", ldb.FLAG_MOD_ADD, "objectClass") self.samdb.add(m) # Get new security descriptor ds_sd_flags = (security.SECINFO_OWNER | security.SECINFO_GROUP | security.SECINFO_DACL) msg = get_gpo_info(self.samdb, gpo=gpo, sd_flags=ds_sd_flags)[0] ds_sd_ndr = msg['nTSecurityDescriptor'][0] ds_sd = ndr_unpack(security.descriptor, ds_sd_ndr).as_sddl() # Create a file system security descriptor domain_sid = security.dom_sid(self.samdb.get_domain_sid()) sddl = dsacl2fsacl(ds_sd, domain_sid) fs_sd = security.descriptor.from_sddl(sddl, domain_sid) # Copy GPO directory create_directory_hier(conn, sharepath) # Set ACL sio = (security.SECINFO_OWNER | security.SECINFO_GROUP | security.SECINFO_DACL | security.SECINFO_PROTECTED_DACL) conn.set_acl(sharepath, fs_sd, sio) # Copy GPO files over SMB copy_directory_local_to_remote(conn, gpodir, sharepath) m = ldb.Message() m.dn = gpo_dn m['a02'] = ldb.MessageElement(displayname, ldb.FLAG_MOD_REPLACE, "displayName") m['a03'] = ldb.MessageElement(unc_path, ldb.FLAG_MOD_REPLACE, "gPCFileSysPath") m['a05'] = ldb.MessageElement("0", ldb.FLAG_MOD_REPLACE, "versionNumber") m['a07'] = ldb.MessageElement("2", ldb.FLAG_MOD_REPLACE, "gpcFunctionalityVersion") m['a04'] = ldb.MessageElement("0", ldb.FLAG_MOD_REPLACE, "flags") controls = ["permissive_modify:0"] self.samdb.modify(m, controls=controls) except Exception: self.samdb.transaction_cancel() raise else: self.samdb.transaction_commit() self.outf.write("GPO '%s' created as %s\n" % (displayname, gpo))
class drs_Replicate(object): """DRS replication calls""" def __init__(self, binding_string, lp, creds, samdb, invocation_id): self.drs = drsuapi.drsuapi(binding_string, lp, creds) (self.drs_handle, self.supported_extensions) = drs_DsBind(self.drs) self.net = Net(creds=creds, lp=lp) self.samdb = samdb if not isinstance(invocation_id, misc.GUID): raise RuntimeError("Must supply GUID for invocation_id") if invocation_id == misc.GUID("00000000-0000-0000-0000-000000000000"): raise RuntimeError("Must not set GUID 00000000-0000-0000-0000-000000000000 as invocation_id") self.replication_state = self.net.replicate_init(self.samdb, lp, self.drs, invocation_id) def drs_get_rodc_partial_attribute_set(self): """get a list of attributes for RODC replication""" partial_attribute_set = drsuapi.DsPartialAttributeSet() partial_attribute_set.version = 1 attids = [] # the exact list of attids we send is quite critical. Note that # we do ask for the secret attributes, but set SPECIAL_SECRET_PROCESSING # to zero them out schema_dn = self.samdb.get_schema_basedn() res = self.samdb.search( base=schema_dn, scope=ldb.SCOPE_SUBTREE, expression="objectClass=attributeSchema", attrs=["lDAPDisplayName", "systemFlags", "searchFlags"], ) for r in res: ldap_display_name = r["lDAPDisplayName"][0] if "systemFlags" in r: system_flags = r["systemFlags"][0] if int(system_flags) & ( samba.dsdb.DS_FLAG_ATTR_NOT_REPLICATED | samba.dsdb.DS_FLAG_ATTR_IS_CONSTRUCTED ): continue if "searchFlags" in r: search_flags = r["searchFlags"][0] if int(search_flags) & samba.dsdb.SEARCH_FLAG_RODC_ATTRIBUTE: continue attid = self.samdb.get_attid_from_lDAPDisplayName(ldap_display_name) attids.append(int(attid)) # the attids do need to be sorted, or windows doesn't return # all the attributes we need attids.sort() partial_attribute_set.attids = attids partial_attribute_set.num_attids = len(attids) return partial_attribute_set def replicate( self, dn, source_dsa_invocation_id, destination_dsa_guid, schema=False, exop=drsuapi.DRSUAPI_EXOP_NONE, rodc=False, replica_flags=None, ): """replicate a single DN""" # setup for a GetNCChanges call req8 = drsuapi.DsGetNCChangesRequest8() req8.destination_dsa_guid = destination_dsa_guid req8.source_dsa_invocation_id = source_dsa_invocation_id req8.naming_context = drsuapi.DsReplicaObjectIdentifier() req8.naming_context.dn = dn req8.highwatermark = drsuapi.DsReplicaHighWaterMark() req8.highwatermark.tmp_highest_usn = 0 req8.highwatermark.reserved_usn = 0 req8.highwatermark.highest_usn = 0 req8.uptodateness_vector = None if replica_flags is not None: req8.replica_flags = replica_flags elif exop == drsuapi.DRSUAPI_EXOP_REPL_SECRET: req8.replica_flags = 0 else: req8.replica_flags = ( drsuapi.DRSUAPI_DRS_INIT_SYNC | drsuapi.DRSUAPI_DRS_PER_SYNC | drsuapi.DRSUAPI_DRS_GET_ANC | drsuapi.DRSUAPI_DRS_NEVER_SYNCED ) if rodc: req8.replica_flags |= drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING else: req8.replica_flags |= drsuapi.DRSUAPI_DRS_WRIT_REP req8.max_object_count = 402 req8.max_ndr_size = 402116 req8.extended_op = exop req8.fsmo_info = 0 req8.partial_attribute_set = None req8.partial_attribute_set_ex = None req8.mapping_ctr.num_mappings = 0 req8.mapping_ctr.mappings = None if not schema and rodc: req8.partial_attribute_set = self.drs_get_rodc_partial_attribute_set() if self.supported_extensions & drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8: req_level = 8 req = req8 else: req_level = 5 req5 = drsuapi.DsGetNCChangesRequest5() for a in dir(req5): if a[0] != "_": setattr(req5, a, getattr(req8, a)) req = req5 while True: (level, ctr) = self.drs.DsGetNCChanges(self.drs_handle, req_level, req) if ctr.first_object is None and ctr.object_count != 0: raise RuntimeError( "DsGetNCChanges: NULL first_object with object_count={0:d}".format((ctr.object_count)) ) self.net.replicate_chunk(self.replication_state, level, ctr, schema=schema, req_level=req_level, req=req) if ctr.more_data == 0: break req.highwatermark = ctr.new_highwatermark
class drs_Replicate(object): '''DRS replication calls''' def __init__(self, binding_string, lp, creds, samdb, invocation_id): self.drs = drsuapi.drsuapi(binding_string, lp, creds) (self.drs_handle, self.supported_extensions) = drs_DsBind(self.drs) self.net = Net(creds=creds, lp=lp) self.samdb = samdb if not isinstance(invocation_id, misc.GUID): raise RuntimeError("Must supply GUID for invocation_id") if invocation_id == misc.GUID("00000000-0000-0000-0000-000000000000"): raise RuntimeError( "Must not set GUID 00000000-0000-0000-0000-000000000000 as invocation_id" ) self.replication_state = self.net.replicate_init( self.samdb, lp, self.drs, invocation_id) self.more_flags = 0 def _should_retry_with_get_tgt(self, error_code, req): # If the error indicates we fail to resolve a target object for a # linked attribute, then we should retry the request with GET_TGT # (if we support it and haven't already tried that) # TODO fix up the below line when we next update werror_err_table.txt # and pull in the new error-code # return (error_code == werror.WERR_DS_DRA_RECYCLED_TARGET and return (error_code == 0x21bf and (req.more_flags & drsuapi.DRSUAPI_DRS_GET_TGT) == 0 and self.supported_extensions & drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V10) def process_chunk(self, level, ctr, schema, req_level, req, first_chunk): '''Processes a single chunk of received replication data''' # pass the replication into the py_net.c python bindings for processing self.net.replicate_chunk(self.replication_state, level, ctr, schema=schema, req_level=req_level, req=req) def replicate(self, dn, source_dsa_invocation_id, destination_dsa_guid, schema=False, exop=drsuapi.DRSUAPI_EXOP_NONE, rodc=False, replica_flags=None, full_sync=True, sync_forced=False, more_flags=0): '''replicate a single DN''' # setup for a GetNCChanges call if self.supported_extensions & drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V10: req = drsuapi.DsGetNCChangesRequest10() req.more_flags = (more_flags | self.more_flags) req_level = 10 else: req_level = 8 req = drsuapi.DsGetNCChangesRequest8() req.destination_dsa_guid = destination_dsa_guid req.source_dsa_invocation_id = source_dsa_invocation_id req.naming_context = drsuapi.DsReplicaObjectIdentifier() req.naming_context.dn = dn # Default to a full replication if we don't find an upToDatenessVector udv = None hwm = drsuapi.DsReplicaHighWaterMark() hwm.tmp_highest_usn = 0 hwm.reserved_usn = 0 hwm.highest_usn = 0 if not full_sync: res = self.samdb.search(base=dn, scope=ldb.SCOPE_BASE, attrs=["repsFrom"]) if "repsFrom" in res[0]: for reps_from_packed in res[0]["repsFrom"]: reps_from_obj = ndr_unpack(drsblobs.repsFromToBlob, reps_from_packed) if reps_from_obj.ctr.source_dsa_invocation_id == source_dsa_invocation_id: hwm = reps_from_obj.ctr.highwatermark udv = drsuapi.DsReplicaCursorCtrEx() udv.version = 1 udv.reserved1 = 0 udv.reserved2 = 0 cursors_v1 = [] cursors_v2 = dsdb._dsdb_load_udv_v2( self.samdb, self.samdb.get_default_basedn()) for cursor_v2 in cursors_v2: cursor_v1 = drsuapi.DsReplicaCursor() cursor_v1.source_dsa_invocation_id = cursor_v2.source_dsa_invocation_id cursor_v1.highest_usn = cursor_v2.highest_usn cursors_v1.append(cursor_v1) udv.cursors = cursors_v1 udv.count = len(cursors_v1) req.highwatermark = hwm req.uptodateness_vector = udv if replica_flags is not None: req.replica_flags = replica_flags elif exop == drsuapi.DRSUAPI_EXOP_REPL_SECRET: req.replica_flags = 0 else: req.replica_flags = (drsuapi.DRSUAPI_DRS_INIT_SYNC | drsuapi.DRSUAPI_DRS_PER_SYNC | drsuapi.DRSUAPI_DRS_GET_ANC | drsuapi.DRSUAPI_DRS_NEVER_SYNCED | drsuapi.DRSUAPI_DRS_GET_ALL_GROUP_MEMBERSHIP) if rodc: req.replica_flags |= ( drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING) else: req.replica_flags |= drsuapi.DRSUAPI_DRS_WRIT_REP if sync_forced: req.replica_flags |= drsuapi.DRSUAPI_DRS_SYNC_FORCED req.max_object_count = 402 req.max_ndr_size = 402116 req.extended_op = exop req.fsmo_info = 0 req.partial_attribute_set = None req.partial_attribute_set_ex = None req.mapping_ctr.num_mappings = 0 req.mapping_ctr.mappings = None if not schema and rodc: req.partial_attribute_set = drs_get_rodc_partial_attribute_set( self.samdb) if not self.supported_extensions & drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8: req_level = 5 req5 = drsuapi.DsGetNCChangesRequest5() for a in dir(req5): if a[0] != '_': setattr(req5, a, getattr(req, a)) req = req5 num_objects = 0 num_links = 0 first_chunk = True while True: (level, ctr) = self.drs.DsGetNCChanges(self.drs_handle, req_level, req) if ctr.first_object is None and ctr.object_count != 0: raise RuntimeError( "DsGetNCChanges: NULL first_object with object_count=%u" % (ctr.object_count)) try: self.process_chunk(level, ctr, schema, req_level, req, first_chunk) except WERRORError as e: # Check if retrying with the GET_TGT flag set might resolve this error if self._should_retry_with_get_tgt(e.args[0], req): print("Missing target object - retrying with DRS_GET_TGT") req.more_flags |= drsuapi.DRSUAPI_DRS_GET_TGT # try sending the request again (this has the side-effect # of causing the DC to restart the replication from scratch) first_chunk = True continue else: raise e first_chunk = False num_objects += ctr.object_count # Cope with servers that do not return level 6, so do not return any links try: num_links += ctr.linked_attributes_count except AttributeError: pass if ctr.more_data == 0: break # update the request's HWM so we get the next chunk drs_copy_highwater_mark(req.highwatermark, ctr.new_highwatermark) return (num_objects, num_links)
def run(self, keytab, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() net = Net(None, lp, server=credopts.ipaddress) net.export_keytab(keytab=keytab)
def run(self, name, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) net = Net(creds, lp, server=credopts.ipaddress) net.delete_user(name)
def run(self, domain, role=None, sambaopts=None, credopts=None, versionopts=None, server=None, site=None, targetdir=None, domain_critical_only=False, parent_domain=None, machinepass=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) net = Net(creds, lp, server=credopts.ipaddress) if site is None: site = "Default-First-Site-Name" netbios_name = lp.get("netbios name") if not role is None: role = role.upper() if role is None or role == "MEMBER": (join_password, sid, domain_name) = net.join_member(domain, netbios_name, LIBNET_JOIN_AUTOMATIC, machinepass=machinepass) self.outf.write("Joined domain %s (%s)\n" % (domain_name, sid)) return elif role == "DC": join_DC(server=server, creds=creds, lp=lp, domain=domain, site=site, netbios_name=netbios_name, targetdir=targetdir, domain_critical_only=domain_critical_only, machinepass=machinepass) return elif role == "RODC": join_RODC(server=server, creds=creds, lp=lp, domain=domain, site=site, netbios_name=netbios_name, targetdir=targetdir, domain_critical_only=domain_critical_only, machinepass=machinepass) return elif role == "SUBDOMAIN": netbios_domain = lp.get("workgroup") if parent_domain is None: parent_domain = ".".join(domain.split(".")[1:]) join_subdomain(server=server, creds=creds, lp=lp, dnsdomain=domain, parent_domain=parent_domain, site=site, netbios_name=netbios_name, netbios_domain=netbios_domain, targetdir=targetdir, machinepass=machinepass) return else: raise CommandError( "Invalid role '%s' (possible values: MEMBER, DC, RODC, SUBDOMAIN)" % role)
def run(self, sambaopts=None, credopts=None, versionopts=None, server=None, targetdir=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) net = Net(creds, lp, server=credopts.ipaddress) netbios_name = lp.get("netbios name") samdb = SamDB(session_info=system_session(), credentials=creds, lp=lp) if not server: res = samdb.search( expression='(&(objectClass=computer)(serverReferenceBL=*))', attrs=["dnsHostName", "name"]) if (len(res) == 0): raise CommandError("Unable to search for servers") if (len(res) == 1): raise CommandError("You are the latest server in the domain") server = None for e in res: if str(e["name"]).lower() != netbios_name.lower(): server = e["dnsHostName"] break ntds_guid = samdb.get_ntds_GUID() msg = samdb.search(base=str(samdb.get_config_basedn()), scope=ldb.SCOPE_SUBTREE, expression="(objectGUID=%s)" % ntds_guid, attrs=['options']) if len(msg) == 0 or "options" not in msg[0]: raise CommandError("Failed to find options on %s" % ntds_guid) ntds_dn = msg[0].dn dsa_options = int(str(msg[0]['options'])) res = samdb.search(expression="(fSMORoleOwner=%s)" % str(ntds_dn), controls=["search_options:1:2"]) if len(res) != 0: raise CommandError( "Current DC is still the owner of %d role(s), use the role command to transfer roles to another DC" ) print "Using %s as partner server for the demotion" % server (drsuapiBind, drsuapi_handle, supportedExtensions) = drsuapi_connect(server, lp, creds) print "Desactivating inbound replication" nmsg = ldb.Message() nmsg.dn = msg[0].dn dsa_options |= DS_NTDSDSA_OPT_DISABLE_INBOUND_REPL nmsg["options"] = ldb.MessageElement(str(dsa_options), ldb.FLAG_MOD_REPLACE, "options") samdb.modify(nmsg) if not (dsa_options & DS_NTDSDSA_OPT_DISABLE_OUTBOUND_REPL) and not samdb.am_rodc(): print "Asking partner server %s to synchronize from us" % server for part in (samdb.get_schema_basedn(), samdb.get_config_basedn(), samdb.get_root_basedn()): try: sendDsReplicaSync(drsuapiBind, drsuapi_handle, ntds_guid, str(part), drsuapi.DRSUAPI_DRS_WRIT_REP) except drsException, e: print "Error while demoting, re-enabling inbound replication" dsa_options ^= DS_NTDSDSA_OPT_DISABLE_INBOUND_REPL nmsg["options"] = ldb.MessageElement( str(dsa_options), ldb.FLAG_MOD_REPLACE, "options") samdb.modify(nmsg) raise CommandError( "Error while sending a DsReplicaSync for partion %s" % str(part), e)