s4-subdomain: create trust record with forest root DC
authorAndrew Tridgell <tridge@samba.org>
Sat, 1 Oct 2011 00:58:52 +0000 (10:58 +1000)
committerAndrew Tridgell <tridge@samba.org>
Tue, 4 Oct 2011 05:40:59 +0000 (07:40 +0200)
when we create a sub-subdomain we need to use the forest naming master
to setup the partition changes for the new subdomain. We also need to
setup the trust with the forest root, as that allows us to create the
needed _msdcs DNS entries in the forest

Autobuild-User: Andrew Tridgell <tridge@samba.org>
Autobuild-Date: Tue Oct  4 07:40:59 CEST 2011 on sn-devel-104

source4/scripting/python/samba/join.py

index 38f5c8aac18ceebaebb25da8f8ac5c25367a457a..731f0b501bc48197621a962ce5ca91e38ad04312 100644 (file)
@@ -84,6 +84,7 @@ class dc_join(object):
         ctx.config_dn = str(ctx.samdb.get_config_basedn())
         ctx.domsid = ctx.samdb.get_domain_sid()
         ctx.domain_name = ctx.get_domain_name()
+        ctx.forest_domain_name = ctx.get_forest_domain_name()
         ctx.invocation_id = misc.GUID(str(uuid.uuid4()))
 
         ctx.dc_ntds_dn = ctx.get_dsServiceName()
@@ -185,7 +186,7 @@ class dc_join(object):
                 lsaconn.DeleteTrustedDomain(pol_handle, info.info_ex.sid)
 
                 name = lsa.String()
-                name.string = ctx.domain_name
+                name.string = ctx.forest_domain_name
                 info = lsaconn.QueryTrustedDomainInfoByName(pol_handle, name, lsa.LSA_TRUSTED_DOMAIN_INFO_FULL_INFO)
 
                 lsaconn.DeleteTrustedDomain(pol_handle, info.info_ex.sid)
@@ -226,6 +227,13 @@ class dc_join(object):
                                expression='ncName=%s' % ctx.samdb.get_default_basedn())
         return res[0]["nETBIOSName"][0]
 
+    def get_forest_domain_name(ctx):
+        '''get netbios name of the domain from the partitions record'''
+        partitions_dn = ctx.samdb.get_partitions_dn()
+        res = ctx.samdb.search(base=partitions_dn, scope=ldb.SCOPE_ONELEVEL, attrs=["nETBIOSName"],
+                               expression='ncName=%s' % ctx.samdb.get_root_basedn())
+        return res[0]["nETBIOSName"][0]
+
     def get_parent_partition_dn(ctx):
         '''get the parent domain partition DN from parent DNS name'''
         res = ctx.samdb.search(base=ctx.config_dn, attrs=[],
@@ -233,6 +241,16 @@ class dc_join(object):
                                (ctx.parent_dnsdomain, ldb.OID_COMPARATOR_AND, samba.dsdb.SYSTEM_FLAG_CR_NTDS_DOMAIN))
         return str(res[0].dn)
 
+    def get_naming_master(ctx):
+        '''get the parent domain partition DN from parent DNS name'''
+        res = ctx.samdb.search(base='CN=Partitions,%s' % ctx.config_dn, attrs=['fSMORoleOwner'],
+                               scope=ldb.SCOPE_BASE, controls=["extended_dn:1:1"])
+        if not 'fSMORoleOwner' in res[0]:
+            raise DCJoinException("Can't find naming master on partition DN %s" % ctx.partition_dn)
+        master_guid = str(misc.GUID(ldb.Dn(ctx.samdb, res[0]['fSMORoleOwner'][0]).get_extended_component('GUID')))
+        master_host = '%s._msdcs.%s' % (master_guid, ctx.dnsforest)
+        return master_host
+
     def get_mysid(ctx):
         '''get the SID of the connected user. Only works with w2k8 and later,
            so only used for RODC join'''
@@ -280,9 +298,9 @@ class dc_join(object):
         ctx.samdb.rename(ctx.krbtgt_dn, ctx.new_krbtgt_dn)
 
     def drsuapi_connect(ctx):
-        '''make a DRSUAPI connection to the server'''
+        '''make a DRSUAPI connection to the naming master'''
         binding_options = "seal"
-        if int(ctx.lp.get("log level")) >= 5:
+        if int(ctx.lp.get("log level")) >= 4:
             binding_options += ",print"
         binding_string = "ncacn_ip_tcp:%s[%s]" % (ctx.server, binding_options)
         ctx.drsuapi = drsuapi.drsuapi(binding_string, ctx.lp, ctx.creds)
@@ -784,20 +802,20 @@ class dc_join(object):
                                                          security.SEC_STD_DELETE)
 
         rec = {
-            "dn" : "cn=%s,cn=system,%s" % (ctx.parent_dnsdomain, ctx.base_dn),
+            "dn" : "cn=%s,cn=system,%s" % (ctx.dnsforest, ctx.base_dn),
             "objectclass" : "trustedDomain",
             "trustType" : str(info.trust_type),
             "trustAttributes" : str(info.trust_attributes),
             "trustDirection" : str(info.trust_direction),
-            "flatname" : ctx.parent_domain_name,
-            "trustPartner" : ctx.parent_dnsdomain,
+            "flatname" : ctx.forest_domain_name,
+            "trustPartner" : ctx.dnsforest,
             "trustAuthIncoming" : ndr_pack(outgoing),
             "trustAuthOutgoing" : ndr_pack(outgoing)
             }
         ctx.local_samdb.add(rec)
 
         rec = {
-            "dn" : "cn=%s$,cn=users,%s" % (ctx.parent_domain_name, ctx.base_dn),
+            "dn" : "cn=%s$,cn=users,%s" % (ctx.forest_domain_name, ctx.base_dn),
             "objectclass" : "user",
             "userAccountControl" : str(samba.dsdb.UF_INTERDOMAIN_TRUST_ACCOUNT),
             "clearTextPassword" : ctx.trustdom_pass.encode('utf-16-le')
@@ -914,6 +932,14 @@ def join_subdomain(server=None, creds=None, lp=None, site=None, netbios_name=Non
     ctx.parent_partition_dn = ctx.get_parent_partition_dn()
     ctx.dnsdomain = dnsdomain
     ctx.partition_dn = "CN=%s,CN=Partitions,%s" % (ctx.domain_name, ctx.config_dn)
+    ctx.naming_master = ctx.get_naming_master()
+    if ctx.naming_master != ctx.server:
+        print("Reconnecting to naming master %s" % ctx.naming_master)
+        ctx.server = ctx.naming_master
+        ctx.samdb = SamDB(url="ldap://%s" % ctx.server,
+                          session_info=system_session(),
+                          credentials=ctx.creds, lp=ctx.lp)
+
     ctx.base_dn = samba.dn_from_dns_name(dnsdomain)
     ctx.domsid = str(security.random_sid())
     ctx.acct_dn = None