diff options
author | Andrew Bartlett <abartlet@samba.org> | 2015-10-23 11:23:05 +1300 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2015-10-26 05:11:21 +0100 |
commit | f121173cbf46fe64746d73adf40015c43d5c55fc (patch) | |
tree | ed1e62b96ecd1180c338c70ae37f1fc7f2fda15c /python | |
parent | 1874f592006d8808aa8f3bc97c94d9464a7053cf (diff) | |
download | samba-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.py | 93 |
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", |