From 4faf959102fe8fa7395807339584b34963bbb615 Mon Sep 17 00:00:00 2001 From: Tim Beale Date: Wed, 24 Jul 2019 11:00:01 +1200 Subject: [PATCH] join: Use a specific attribute order for the DsAddEntry nTDSDSA object Joining a Windows domain can throw an error if the HasMasterNCs attribute occurs before msDS-HasMasterNCs. This patch changes the attribute order so that msDS-HasMasterNCs is always first. Previously on python2, the dictionary hash order was arbitrary but constant. By luck, msDS-HasMasterNCs was always before HasMasterNCs, so we never noticed any problem. With python3, the dictionary hash order now changes everytime you run the command, so the order is unpredictable. To enforce a order, we can change to use an OrderedDict, which will return the keys in the order they're added. I've asked Microsoft to clarify the protocol requirement here WRT attribute order. However, in the meantime we may as well fix the problem for users. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14046 RN: When trying to join a Windows domain (with functional level 2008R2) as an AD domain controller, the 'samba-tool domain join' command could throw a python exception: 'RuntimeError ("DsAddEntry failed")'. When this problem occurred, you would also see the message "DsAddEntry failed with status WERR_ACCESS_DENIED info (8363, 'WERR_DS_NO_CROSSREF_FOR_NC')" in the command output. This issue has now been resolved. Note that this problem would only occur on Samba v4.10 when using the Python3 packages. Signed-off-by: Tim Beale Reviewed-by: Andrew Bartlett Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Wed Jul 24 04:18:21 UTC 2019 on sn-devel-184 (cherry picked from commit 256684c7a86301d26d6cf7298fb70e647bf45cf5) --- python/samba/join.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/python/samba/join.py b/python/samba/join.py index da8dcb0..6fe4ee7 100644 --- a/python/samba/join.py +++ b/python/samba/join.py @@ -48,6 +48,7 @@ import time import re import os import tempfile +from collections import OrderedDict from samba.compat import text_type from samba.compat import get_string from samba.netcmd import CommandError @@ -551,11 +552,14 @@ class DCJoinContext(object): '''return the ntdsdsa object to add''' print("Adding %s" % ctx.ntds_dn) - rec = { - "dn": ctx.ntds_dn, - "objectclass": "nTDSDSA", - "systemFlags": str(samba.dsdb.SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE), - "dMDLocation": ctx.schema_dn} + + # When joining Windows, the order of certain attributes (mostly only + # msDS-HasMasterNCs and HasMasterNCs) seems to matter + rec = OrderedDict([ + ("dn", ctx.ntds_dn), + ("objectclass", "nTDSDSA"), + ("systemFlags", str(samba.dsdb.SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE)), + ("dMDLocation", ctx.schema_dn)]) nc_list = [ctx.base_dn, ctx.config_dn, ctx.schema_dn] @@ -571,12 +575,17 @@ class DCJoinContext(object): rec["options"] = "37" else: rec["objectCategory"] = "CN=NTDS-DSA,%s" % ctx.schema_dn + + # Note that Windows seems to have an undocumented requirement that + # the msDS-HasMasterNCs attribute occurs before HasMasterNCs + if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003: + rec["msDS-HasMasterNCs"] = ctx.full_nc_list + rec["HasMasterNCs"] = [] for nc in nc_list: if nc in ctx.full_nc_list: rec["HasMasterNCs"].append(nc) - if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003: - rec["msDS-HasMasterNCs"] = ctx.full_nc_list + rec["options"] = "1" rec["invocationId"] = ndr_pack(ctx.invocation_id) -- 2.7.4