summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2015-10-23 11:23:05 +1300
committerAndrew Bartlett <abartlet@samba.org>2015-10-26 05:11:21 +0100
commitf121173cbf46fe64746d73adf40015c43d5c55fc (patch)
treeed1e62b96ecd1180c338c70ae37f1fc7f2fda15c /python
parent1874f592006d8808aa8f3bc97c94d9464a7053cf (diff)
downloadsamba-f121173cbf46fe64746d73adf40015c43d5c55fc.tar.gz
samba-tool domain demote: Allow to operate on an RODC and a subdomain
On an RODC the local database cannot be modified, and the flags to remove are different, we need instead to remove UF_PARTIAL_SECRETS_ACCOUNT. If we are in a subdomain, then db.get_root_basedn() points to the forest root, not the root of our domain If the removeDsServer() fails with WERR_DS_DRA_NO_REPLICA this may be reasonably considered to be success in this case. Finally, the remove_dc.remove_sysvol_references() is reused for objects not under the computer account. Signed-off-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Garming Sam <garming@catalyst.net.nz> domain demote Signed-off-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Diffstat (limited to 'python')
-rw-r--r--python/samba/netcmd/domain.py93
1 files changed, 53 insertions, 40 deletions
diff --git a/python/samba/netcmd/domain.py b/python/samba/netcmd/domain.py
index e1ae40de54f..aa301f5810b 100644
--- a/python/samba/netcmd/domain.py
+++ b/python/samba/netcmd/domain.py
@@ -71,7 +71,8 @@ from samba.dsdb import (
DS_NTDSDSA_OPT_DISABLE_INBOUND_REPL,
UF_WORKSTATION_TRUST_ACCOUNT,
UF_SERVER_TRUST_ACCOUNT,
- UF_TRUSTED_FOR_DELEGATION
+ UF_TRUSTED_FOR_DELEGATION,
+ UF_PARTIAL_SECRETS_ACCOUNT
)
from samba.provision import (
@@ -734,37 +735,48 @@ class cmd_domain_demote(Command):
self.errf.write("Deactivating inbound replication\n")
- nmsg = ldb.Message()
- nmsg.dn = msg[0].dn
+ if not (dsa_options & DS_NTDSDSA_OPT_DISABLE_OUTBOUND_REPL) and not samdb.am_rodc():
+ 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)
+ 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():
self.errf.write("Asking partner server %s to synchronize from us\n"
% server)
for part in (samdb.get_schema_basedn(),
samdb.get_config_basedn(),
samdb.get_root_basedn()):
+ nc = drsuapi.DsReplicaObjectIdentifier()
+ nc.dn = str(part)
+
+ req1 = drsuapi.DsReplicaSyncRequest1()
+ req1.naming_context = nc;
+ req1.options = drsuapi.DRSUAPI_DRS_WRIT_REP
+ req1.source_dsa_guid = misc.GUID(ntds_guid)
+
try:
- sendDsReplicaSync(drsuapiBind, drsuapi_handle, ntds_guid, str(part), drsuapi.DRSUAPI_DRS_WRIT_REP)
- except drsException, e:
- self.errf.write(
- "Error while demoting, "
+ drsuapiBind.DsReplicaSync(drsuapi_handle, 1, req1)
+ except RuntimeError as (werr, string):
+ if werr == 8452: #WERR_DS_DRA_NO_REPLICA
+ pass
+ else:
+ self.errf.write(
+ "Error while demoting, "
"re-enabling inbound replication\n")
- 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)
+ 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)
try:
remote_samdb = SamDB(url="ldap://%s" % server,
session_info=system_session(),
credentials=creds, lp=lp)
self.errf.write("Changing userControl and container\n")
- res = remote_samdb.search(base=str(remote_samdb.get_root_basedn()),
+ res = remote_samdb.search(base=str(remote_samdb.domain_dn()),
expression="(&(objectClass=user)(sAMAccountName=%s$))" %
netbios_name.upper(),
attrs=["userAccountControl"])
@@ -790,7 +802,7 @@ class cmd_domain_demote(Command):
olduac = uac
- uac ^= (UF_SERVER_TRUST_ACCOUNT|UF_TRUSTED_FOR_DELEGATION)
+ uac &= ~(UF_SERVER_TRUST_ACCOUNT|UF_TRUSTED_FOR_DELEGATION|UF_PARTIAL_SECRETS_ACCOUNT)
uac |= UF_WORKSTATION_TRUST_ACCOUNT
msg = ldb.Message()
@@ -811,13 +823,12 @@ class cmd_domain_demote(Command):
raise CommandError("Error while changing account control", e)
parent = msg.dn.parent()
- rdn = str(res[0].dn)
- rdn = string.replace(rdn, ",%s" % str(parent), "")
+ rdn = "%s=%s" % (res[0].dn.get_rdn_name(), res[0].dn.get_rdn_value())
# Let's move to the Computer container
i = 0
- newrdn = rdn
+ newrdn = str(rdn)
- computer_dn = ldb.Dn(remote_samdb, "CN=Computers,%s" % str(remote_samdb.get_root_basedn()))
+ computer_dn = ldb.Dn(remote_samdb, "CN=Computers,%s" % str(remote_samdb.domain_dn()))
res = remote_samdb.search(base=computer_dn, expression=rdn, scope=ldb.SCOPE_ONELEVEL)
if (len(res) != 0):
@@ -875,34 +886,36 @@ class cmd_domain_demote(Command):
domain = remote_samdb.get_root_basedn()
try:
- sendRemoveDsServer(drsuapiBind, drsuapi_handle, server_dsa_dn, domain)
- except drsException, e:
- self.errf.write(
- "Error while demoting, re-enabling inbound replication\n")
- dsa_options ^= DS_NTDSDSA_OPT_DISABLE_INBOUND_REPL
- nmsg["options"] = ldb.MessageElement(str(dsa_options), ldb.FLAG_MOD_REPLACE, "options")
- samdb.modify(nmsg)
+ req1 = drsuapi.DsRemoveDSServerRequest1()
+ req1.server_dn = str(server_dsa_dn)
+ req1.domain_dn = str(domain)
+ req1.commit = 1
+
+ drsuapiBind.DsRemoveDSServer(drsuapi_handle, 1, req1)
+ except RuntimeError as (werr, string):
+ if not (dsa_options & DS_NTDSDSA_OPT_DISABLE_OUTBOUND_REPL) and not samdb.am_rodc():
+ self.errf.write(
+ "Error while demoting, re-enabling inbound replication\n")
+ dsa_options ^= DS_NTDSDSA_OPT_DISABLE_INBOUND_REPL
+ nmsg["options"] = ldb.MessageElement(str(dsa_options), ldb.FLAG_MOD_REPLACE, "options")
+ samdb.modify(nmsg)
msg = ldb.Message()
msg.dn = newdn
msg["userAccountControl"] = ldb.MessageElement("%d" % uac,
- ldb.FLAG_MOD_REPLACE,
- "userAccountControl")
- print str(dc_dn)
+ ldb.FLAG_MOD_REPLACE,
+ "userAccountControl")
remote_samdb.modify(msg)
remote_samdb.rename(newdn, dc_dn)
- raise CommandError("Error while sending a removeDsServer", e)
+ if werr == 8452: #WERR_DS_DRA_NO_REPLICA
+ raise CommandError("The DC %s is not present on (already removed from) the remote server: " % server_dsa_dn, e)
+ else:
+ raise CommandError("Error while sending a removeDsServer of %s: " % server_dsa_dn, e)
- for s in ("CN=Enterprise,CN=Microsoft System Volumes,CN=System,CN=Configuration",
- "CN=%s,CN=Microsoft System Volumes,CN=System,CN=Configuration" % lp.get("realm"),
- "CN=Domain System Volumes (SYSVOL share),CN=File Replication Service,CN=System"):
- try:
- remote_samdb.delete(ldb.Dn(remote_samdb,
- "%s,%s,%s" % (str(rdn), s, str(remote_samdb.get_root_basedn()))))
- except ldb.LdbError, l:
- pass
+ remove_dc.remove_sysvol_references(remote_samdb, rdn)
+ # These are objects under the computer account that should be deleted
for s in ("CN=Enterprise,CN=NTFRS Subscriptions",
"CN=%s, CN=NTFRS Subscriptions" % lp.get("realm"),
"CN=Domain system Volumes (SYSVOL Share), CN=NTFRS Subscriptions",