1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-28 01:58:17 +03:00

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>
This commit is contained in:
Andrew Bartlett 2015-10-23 11:23:05 +13:00
parent 1874f59200
commit f121173cbf

View File

@ -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,6 +735,7 @@ class cmd_domain_demote(Command):
self.errf.write("Deactivating inbound replication\n")
if not (dsa_options & DS_NTDSDSA_OPT_DISABLE_OUTBOUND_REPL) and not samdb.am_rodc():
nmsg = ldb.Message()
nmsg.dn = msg[0].dn
@ -741,16 +743,26 @@ class cmd_domain_demote(Command):
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:
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")
@ -764,7 +776,7 @@ class cmd_domain_demote(Command):
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,8 +886,14 @@ class cmd_domain_demote(Command):
domain = remote_samdb.get_root_basedn()
try:
sendRemoveDsServer(drsuapiBind, drsuapi_handle, server_dsa_dn, domain)
except drsException, e:
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
@ -889,20 +906,16 @@ class cmd_domain_demote(Command):
msg["userAccountControl"] = ldb.MessageElement("%d" % uac,
ldb.FLAG_MOD_REPLACE,
"userAccountControl")
print str(dc_dn)
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",