summaryrefslogtreecommitdiffstats
path: root/source4/scripting/python/samba/join.py
diff options
context:
space:
mode:
Diffstat (limited to 'source4/scripting/python/samba/join.py')
-rw-r--r--source4/scripting/python/samba/join.py150
1 files changed, 86 insertions, 64 deletions
diff --git a/source4/scripting/python/samba/join.py b/source4/scripting/python/samba/join.py
index ccb9f06f285..195dfc23120 100644
--- a/source4/scripting/python/samba/join.py
+++ b/source4/scripting/python/samba/join.py
@@ -304,40 +304,47 @@ class dc_join(object):
r.value_ctr = 1
- def DsAddEntry(ctx, rec):
+ def DsAddEntry(ctx, recs):
'''add a record via the DRSUAPI DsAddEntry call'''
if ctx.drsuapi is None:
ctx.drsuapi_connect()
if ctx.tmp_samdb is None:
ctx.create_tmp_samdb()
- id = drsuapi.DsReplicaObjectIdentifier()
- id.dn = rec['dn']
-
- attrs = []
- for a in rec:
- if a == 'dn':
- continue
- if not isinstance(rec[a], list):
- v = [rec[a]]
- else:
- v = rec[a]
- rattr = ctx.tmp_samdb.dsdb_DsReplicaAttribute(ctx.tmp_samdb, a, v)
- attrs.append(rattr)
-
- attribute_ctr = drsuapi.DsReplicaAttributeCtr()
- attribute_ctr.num_attributes = len(attrs)
- attribute_ctr.attributes = attrs
-
- object = drsuapi.DsReplicaObject()
- object.identifier = id
- object.attribute_ctr = attribute_ctr
-
- first_object = drsuapi.DsReplicaObjectListItem()
- first_object.object = object
+ objects = []
+ for rec in recs:
+ id = drsuapi.DsReplicaObjectIdentifier()
+ id.dn = rec['dn']
+
+ attrs = []
+ for a in rec:
+ if a == 'dn':
+ continue
+ if not isinstance(rec[a], list):
+ v = [rec[a]]
+ else:
+ v = rec[a]
+ rattr = ctx.tmp_samdb.dsdb_DsReplicaAttribute(ctx.tmp_samdb, a, v)
+ attrs.append(rattr)
+
+ attribute_ctr = drsuapi.DsReplicaAttributeCtr()
+ attribute_ctr.num_attributes = len(attrs)
+ attribute_ctr.attributes = attrs
+
+ object = drsuapi.DsReplicaObject()
+ object.identifier = id
+ object.attribute_ctr = attribute_ctr
+
+ list_object = drsuapi.DsReplicaObjectListItem()
+ list_object.object = object
+ objects.append(list_object)
req2 = drsuapi.DsAddEntryRequest2()
- req2.first_object = first_object
+ req2.first_object = objects[0]
+ prev = req2.first_object
+ for o in objects[1:]:
+ prev.next_object = o
+ prev = o
(level, ctr) = ctx.drsuapi.DsAddEntry(ctx.drsuapi_handle, 2, req2)
if ctr.err_ver != 1:
@@ -349,6 +356,7 @@ class dc_join(object):
if ctr.err_data.dir_err != drsuapi.DRSUAPI_DIRERR_OK:
print("DsAddEntry failed with dir_err %u" % ctr.err_data.dir_err)
raise RuntimeError("DsAddEntry failed")
+ return ctr.objects
def join_add_ntdsdsa(ctx):
@@ -361,17 +369,12 @@ class dc_join(object):
"systemFlags" : str(samba.dsdb.SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE),
"dMDLocation" : ctx.schema_dn}
- if ctx.subdomain:
- # the local subdomain NC doesn't exist at this time
- # so we have to add the base_dn NC later
- nc_list = [ ctx.config_dn, ctx.schema_dn ]
- else:
- nc_list = [ ctx.base_dn, ctx.config_dn, ctx.schema_dn ]
+ nc_list = [ ctx.base_dn, ctx.config_dn, ctx.schema_dn ]
if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003:
rec["msDS-Behavior-Version"] = str(ctx.behavior_version)
- if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003 and not ctx.subdomain:
+ if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003:
rec["msDS-HasDomainNCs"] = ctx.base_dn
if ctx.RODC:
@@ -386,32 +389,13 @@ class dc_join(object):
rec["msDS-HasMasterNCs"] = nc_list
rec["options"] = "1"
rec["invocationId"] = ndr_pack(ctx.invocation_id)
- if ctx.subdomain:
- ctx.samdb.add(rec, ['relax:0'])
- else:
- ctx.DsAddEntry(rec)
+ ctx.DsAddEntry([rec])
# find the GUID of our NTDS DN
res = ctx.samdb.search(base=ctx.ntds_dn, scope=ldb.SCOPE_BASE, attrs=["objectGUID"])
ctx.ntds_guid = misc.GUID(ctx.samdb.schema_format_value("objectGUID", res[0]["objectGUID"][0]))
- def join_modify_ntdsdsa(ctx):
- '''modify the ntdsdsa object to add local partitions'''
- print "Modifying %s using system privileges" % ctx.ntds_dn
-
- # this works around the Enterprise Admins ACL on the NTDSDSA object
- system_session_info = system_session()
- ctx.samdb.set_session_info(system_session_info)
-
- m = ldb.Message()
- m.dn = ldb.Dn(ctx.samdb, ctx.ntds_dn)
- m["HasMasterNCs"] = ldb.MessageElement(ctx.base_dn, ldb.FLAG_MOD_ADD, "HasMasterNCs")
- if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003:
- m["msDS-HasDomainNCs"] = ldb.MessageElement(ctx.base_dn, ldb.FLAG_MOD_ADD, "msDS-HasDomainNCs")
- m["msDS-HasMasterNCs"] = ldb.MessageElement(ctx.base_dn, ldb.FLAG_MOD_ADD, "msDS-HasMasterNCs")
- ctx.samdb.modify(m, controls=['relax:0'])
-
def join_add_objects(ctx):
'''add the various objects needed for the join'''
if ctx.acct_dn:
@@ -440,9 +424,11 @@ class dc_join(object):
rec = {
"dn": ctx.server_dn,
"objectclass" : "server",
+ # windows uses 50000000 decimal for systemFlags. A windows hex/decimal mixup bug?
"systemFlags" : str(samba.dsdb.SYSTEM_FLAG_CONFIG_ALLOW_RENAME |
samba.dsdb.SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE |
samba.dsdb.SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE),
+ # windows seems to add the dnsHostName later
"dnsHostName" : ctx.dnshostname}
if ctx.acct_dn:
@@ -507,9 +493,6 @@ class dc_join(object):
def join_add_objects2(ctx):
'''add the various objects needed for the join, for subdomains post replication'''
- if not ctx.subdomain:
- return
-
print "Adding %s" % ctx.partition_dn
# NOTE: windows sends a ntSecurityDescriptor here, we
# let it default
@@ -524,8 +507,47 @@ class dc_join(object):
"systemFlags" : str(samba.dsdb.SYSTEM_FLAG_CR_NTDS_NC|samba.dsdb.SYSTEM_FLAG_CR_NTDS_DOMAIN)}
if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003:
rec["msDS-Behavior-Version"] = str(ctx.behavior_version)
- ctx.DsAddEntry(rec)
+ rec2 = {
+ "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 ]
+
+ if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003:
+ rec2["msDS-Behavior-Version"] = str(ctx.behavior_version)
+
+ if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003:
+ rec2["msDS-HasDomainNCs"] = ctx.base_dn
+
+ rec2["objectCategory"] = "CN=NTDS-DSA,%s" % ctx.schema_dn
+ rec2["HasMasterNCs"] = nc_list
+ if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003:
+ rec2["msDS-HasMasterNCs"] = nc_list
+ rec2["options"] = "1"
+ rec2["invocationId"] = ndr_pack(ctx.invocation_id)
+
+ objects = ctx.DsAddEntry([rec, rec2])
+ if len(objects) != 2:
+ raise DCJoinException("Expected 2 objects from DsAddEntry")
+
+ ctx.ntds_guid = objects[1].guid
+
+ print("Replicating partition DN")
+ ctx.repl.replicate(ctx.partition_dn,
+ misc.GUID("00000000-0000-0000-0000-000000000000"),
+ ctx.ntds_guid,
+ exop=drsuapi.DRSUAPI_EXOP_REPL_OBJ,
+ replica_flags=drsuapi.DRSUAPI_DRS_WRIT_REP)
+
+ print("Replicating NTDS DN")
+ ctx.repl.replicate(ctx.ntds_dn,
+ misc.GUID("00000000-0000-0000-0000-000000000000"),
+ ctx.ntds_guid,
+ exop=drsuapi.DRSUAPI_EXOP_REPL_OBJ,
+ replica_flags=drsuapi.DRSUAPI_DRS_WRIT_REP)
def join_provision(ctx):
'''provision the local SAM'''
@@ -565,14 +587,11 @@ class dc_join(object):
ctx.local_samdb = ctx.samdb
print("Finding domain GUID from ncName")
- res = ctx.samdb.search(base=ctx.partition_dn, scope=ldb.SCOPE_BASE, attrs=['ncName'],
- controls=["extended_dn:1:1"])
+ res = ctx.local_samdb.search(base=ctx.partition_dn, scope=ldb.SCOPE_BASE, attrs=['ncName'],
+ controls=["extended_dn:1:1"])
domguid = str(misc.GUID(ldb.Dn(ctx.samdb, res[0]['ncName'][0]).get_extended_component('GUID')))
print("Got domain GUID %s" % domguid)
-
- ctx.join_add_ntdsdsa()
-
print("Calling own domain provision")
logger = logging.getLogger("provision")
@@ -597,6 +616,7 @@ class dc_join(object):
try:
source_dsa_invocation_id = misc.GUID(ctx.samdb.get_invocation_id())
if ctx.ntds_guid is None:
+ print("Using DS_BIND_GUID_W2K3")
destination_dsa_guid = misc.GUID(drsuapi.DRSUAPI_DS_BIND_GUID_W2K3)
else:
destination_dsa_guid = ctx.ntds_guid
@@ -634,6 +654,9 @@ class dc_join(object):
repl.replicate(ctx.new_krbtgt_dn, source_dsa_invocation_id,
destination_dsa_guid,
exop=drsuapi.DRSUAPI_EXOP_REPL_SECRET, rodc=True)
+ ctx.repl = repl
+ ctx.source_dsa_invocation_id = source_dsa_invocation_id
+ ctx.destination_dsa_guid = destination_dsa_guid
print "Committing SAM database"
except:
@@ -787,12 +810,11 @@ class dc_join(object):
try:
ctx.join_add_objects()
ctx.join_provision()
- ctx.join_add_objects2()
ctx.join_replicate()
if ctx.subdomain:
+ ctx.join_add_objects2()
ctx.join_provision_own_domain()
ctx.join_setup_trusts()
- ctx.join_modify_ntdsdsa()
ctx.join_finalise()
except Exception:
print "Join failed - cleaning up"