s4-provision Add initial support for joining as a new subdomain
authorAndrew Bartlett <abartlet@samba.org>
Wed, 24 Aug 2011 05:39:51 +0000 (15:39 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 13 Sep 2011 05:37:11 +0000 (15:37 +1000)
To do this we need to reorganise a lot of the provision code, so that
we can create the framework for the inbound replicaton of the config
and schema partitions and then add in the new subdomain locally.

Andrew Bartlett

source4/scripting/python/samba/join.py
source4/scripting/python/samba/netcmd/domain.py
source4/scripting/python/samba/provision/__init__.py
source4/setup/provision_self_join.ldif
source4/setup/provision_self_join_config.ldif [new file with mode: 0644]
source4/setup/provision_self_join_modify.ldif
source4/setup/provision_self_join_modify_config.ldif [new file with mode: 0644]

index 3d81a296f7c82b3bab878f5b8b05b3ed7451d862..1759990deb96d2fae492fda70a1b453c278a74e8 100644 (file)
@@ -27,9 +27,10 @@ import ldb, samba, sys, os, uuid
 from samba.ndr import ndr_pack
 from samba.dcerpc import security, drsuapi, misc, nbt
 from samba.credentials import Credentials, DONT_USE_KERBEROS
-from samba.provision import secretsdb_self_join, provision, FILL_DRS
+from samba.provision import secretsdb_self_join, provision, provision_fill, FILL_DRS, FILL_SUBDOMAIN
 from samba.schema import Schema
 from samba.net import Net
+from samba.dcerpc import security
 import logging
 import talloc
 
@@ -82,9 +83,6 @@ class dc_join(object):
         ctx.domsid = ctx.samdb.get_domain_sid()
         ctx.domain_name = ctx.get_domain_name()
 
-        lp.set("workgroup", ctx.domain_name)
-        print("workgroup is %s" % ctx.domain_name)
-
         ctx.dc_ntds_dn = ctx.get_dsServiceName()
         ctx.dc_dnsHostName = ctx.get_dnsHostName()
         ctx.behavior_version = ctx.get_behavior_version()
@@ -105,9 +103,6 @@ class dc_join(object):
         ctx.dnshostname = "%s.%s" % (ctx.myname, ctx.dnsdomain)
 
         ctx.realm = ctx.dnsdomain
-        lp.set("realm", ctx.realm)
-
-        print("realm is %s" % ctx.realm)
 
         ctx.acct_dn = "CN=%s,OU=Domain Controllers,%s" % (ctx.myname, ctx.base_dn)
 
@@ -314,23 +309,24 @@ class dc_join(object):
 
     def join_add_objects(ctx):
         '''add the various objects needed for the join'''
-        print "Adding %s" % ctx.acct_dn
-        rec = {
-            "dn" : ctx.acct_dn,
-            "objectClass": "computer",
-            "displayname": ctx.samname,
-            "samaccountname" : ctx.samname,
-            "userAccountControl" : str(ctx.userAccountControl | samba.dsdb.UF_ACCOUNTDISABLE),
-            "dnshostname" : ctx.dnshostname}
-        if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2008:
-            rec['msDS-SupportedEncryptionTypes'] = str(samba.dsdb.ENC_ALL_TYPES)
-        if ctx.managedby:
-            rec["managedby"] = ctx.managedby
-        if ctx.never_reveal_sid:
-            rec["msDS-NeverRevealGroup"] = ctx.never_reveal_sid
-        if ctx.reveal_sid:
-            rec["msDS-RevealOnDemandGroup"] = ctx.reveal_sid
-        ctx.samdb.add(rec)
+        if ctx.acct_dn:
+            print "Adding %s" % ctx.acct_dn
+            rec = {
+                "dn" : ctx.acct_dn,
+                "objectClass": "computer",
+                "displayname": ctx.samname,
+                "samaccountname" : ctx.samname,
+                "userAccountControl" : str(ctx.userAccountControl | samba.dsdb.UF_ACCOUNTDISABLE),
+                "dnshostname" : ctx.dnshostname}
+            if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2008:
+                rec['msDS-SupportedEncryptionTypes'] = str(samba.dsdb.ENC_ALL_TYPES)
+            if ctx.managedby:
+                rec["managedby"] = ctx.managedby
+            if ctx.never_reveal_sid:
+                rec["msDS-NeverRevealGroup"] = ctx.never_reveal_sid
+            if ctx.reveal_sid:
+                rec["msDS-RevealOnDemandGroup"] = ctx.reveal_sid
+            ctx.samdb.add(rec)
 
         if ctx.krbtgt_dn:
             ctx.add_krbtgt_account()
@@ -342,8 +338,11 @@ class dc_join(object):
             "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),
-            "serverReference" : ctx.acct_dn,
             "dnsHostName" : ctx.dnshostname}
+
+        if ctx.acct_dn:
+            rec["serverReference"] = ctx.acct_dn
+
         ctx.samdb.add(rec)
 
         # FIXME: the partition (NC) assignment has to be made dynamic
@@ -388,7 +387,7 @@ class dc_join(object):
                 "fromServer" : ctx.dc_ntds_dn}
             ctx.samdb.add(rec)
 
-        if ctx.topology_dn:
+        if ctx.topology_dn and ctx.acct_dn:
             print "Adding %s" % ctx.topology_dn
             rec = {
                 "dn" : ctx.topology_dn,
@@ -397,31 +396,32 @@ class dc_join(object):
                 "serverReference" : ctx.ntds_dn}
             ctx.samdb.add(rec)
 
-        print "Adding SPNs to %s" % ctx.acct_dn
-        m = ldb.Message()
-        m.dn = ldb.Dn(ctx.samdb, ctx.acct_dn)
-        for i in range(len(ctx.SPNs)):
-            ctx.SPNs[i] = ctx.SPNs[i].replace("$NTDSGUID", str(ctx.ntds_guid))
-        m["servicePrincipalName"] = ldb.MessageElement(ctx.SPNs,
-                                                       ldb.FLAG_MOD_ADD,
-                                                       "servicePrincipalName")
-        ctx.samdb.modify(m)
-
-        print "Setting account password for %s" % ctx.samname
-        ctx.samdb.setpassword("(&(objectClass=user)(sAMAccountName=%s))" % ldb.binary_encode(ctx.samname),
-                              ctx.acct_pass,
-                              force_change_at_next_login=False,
-                              username=ctx.samname)
-        res = ctx.samdb.search(base=ctx.acct_dn, scope=ldb.SCOPE_BASE, attrs=["msDS-keyVersionNumber"])
-        ctx.key_version_number = int(res[0]["msDS-keyVersionNumber"][0])
-
-        print("Enabling account")
-        m = ldb.Message()
-        m.dn = ldb.Dn(ctx.samdb, ctx.acct_dn)
-        m["userAccountControl"] = ldb.MessageElement(str(ctx.userAccountControl),
-                                                     ldb.FLAG_MOD_REPLACE,
-                                                     "userAccountControl")
-        ctx.samdb.modify(m)
+        if ctx.acct_dn:
+            print "Adding SPNs to %s" % ctx.acct_dn
+            m = ldb.Message()
+            m.dn = ldb.Dn(ctx.samdb, ctx.acct_dn)
+            for i in range(len(ctx.SPNs)):
+                ctx.SPNs[i] = ctx.SPNs[i].replace("$NTDSGUID", str(ctx.ntds_guid))
+            m["servicePrincipalName"] = ldb.MessageElement(ctx.SPNs,
+                                                           ldb.FLAG_MOD_ADD,
+                                                           "servicePrincipalName")
+            ctx.samdb.modify(m)
+
+            print "Setting account password for %s" % ctx.samname
+            ctx.samdb.setpassword("(&(objectClass=user)(sAMAccountName=%s))" % ldb.binary_encode(ctx.samname),
+                                  ctx.acct_pass,
+                                  force_change_at_next_login=False,
+                                  username=ctx.samname)
+            res = ctx.samdb.search(base=ctx.acct_dn, scope=ldb.SCOPE_BASE, attrs=["msDS-keyVersionNumber"])
+            ctx.key_version_number = int(res[0]["msDS-keyVersionNumber"][0])
+
+            print("Enabling account")
+            m = ldb.Message()
+            m.dn = ldb.Dn(ctx.samdb, ctx.acct_dn)
+            m["userAccountControl"] = ldb.MessageElement(str(ctx.userAccountControl),
+                                                         ldb.FLAG_MOD_REPLACE,
+                                                         "userAccountControl")
+            ctx.samdb.modify(m)
 
     def join_provision(ctx):
         '''provision the local SAM'''
@@ -445,6 +445,24 @@ class dc_join(object):
         ctx.local_samdb = presult.samdb
         ctx.lp          = presult.lp
         ctx.paths       = presult.paths
+        ctx.names       = presult.names
+
+    def join_provision_own_domain(ctx):
+        '''provision the local SAM'''
+
+        print "Calling bare provision"
+
+        logger = logging.getLogger("provision")
+        logger.addHandler(logging.StreamHandler(sys.stdout))
+
+        secrets_ldb = Ldb(ctx.paths.secrets, session_info=system_session(), lp=ctx.lp)
+
+        presult = provision_fill(ctx.local_samdb, secrets_ldb,
+                                 logger, ctx.names, ctx.paths, domainsid=security.dom_sid(ctx.domsid),
+                                 targetdir=ctx.targetdir, samdb_fill=FILL_SUBDOMAIN,
+                                 machinepass=ctx.acct_pass, serverrole="domain controller",
+                                 lp=ctx.lp)
+        print "Provision OK for domain %s" % ctx.names.dnsdomain
 
 
     def join_replicate(ctx):
@@ -478,9 +496,10 @@ class dc_join(object):
             repl.replicate(ctx.config_dn, source_dsa_invocation_id,
                     destination_dsa_guid, rodc=ctx.RODC,
                     replica_flags=ctx.replica_flags)
-            repl.replicate(ctx.base_dn, source_dsa_invocation_id,
-                    destination_dsa_guid, rodc=ctx.RODC,
-                    replica_flags=ctx.domain_replica_flags)
+            if not ctx.subdomain:
+                repl.replicate(ctx.base_dn, source_dsa_invocation_id,
+                               destination_dsa_guid, rodc=ctx.RODC,
+                               replica_flags=ctx.domain_replica_flags)
             if ctx.RODC:
                 repl.replicate(ctx.acct_dn, source_dsa_invocation_id,
                         destination_dsa_guid,
@@ -526,7 +545,10 @@ class dc_join(object):
             ctx.join_add_objects()
             ctx.join_provision()
             ctx.join_replicate()
-            ctx.join_finalise()
+            if ctx.subdomain:
+                ctx.join_provision_own_domain()
+            else:
+                ctx.join_finalise()
         except Exception:
             print "Join failed - cleaning up"
             ctx.cleanup_old_join()
@@ -539,6 +561,12 @@ def join_RODC(server=None, creds=None, lp=None, site=None, netbios_name=None,
 
     ctx = dc_join(server, creds, lp, site, netbios_name, targetdir, domain)
 
+    lp.set("workgroup", ctx.domain_name)
+    print("workgroup is %s" % ctx.domain_name)
+
+    lp.set("realm", ctx.realm)
+    print("realm is %s" % ctx.realm)
+
     ctx.krbtgt_dn = "CN=krbtgt_%s,CN=Users,%s" % (ctx.myname, ctx.base_dn)
 
     # setup some defaults for accounts that should be replicated to this RODC
@@ -584,6 +612,12 @@ def join_DC(server=None, creds=None, lp=None, site=None, netbios_name=None,
     """join as a DC"""
     ctx = dc_join(server, creds, lp, site, netbios_name, targetdir, domain)
 
+    lp.set("workgroup", ctx.domain_name)
+    print("workgroup is %s" % ctx.domain_name)
+
+    lp.set("realm", ctx.realm)
+    print("realm is %s" % ctx.realm)
+
     ctx.userAccountControl = samba.dsdb.UF_SERVER_TRUST_ACCOUNT | samba.dsdb.UF_TRUSTED_FOR_DELEGATION
 
     ctx.SPNs.append('E3514235-4B06-11D1-AB04-00C04FC2DCD2/$NTDSGUID/%s' % ctx.dnsdomain)
@@ -600,3 +634,31 @@ def join_DC(server=None, creds=None, lp=None, site=None, netbios_name=None,
 
     ctx.do_join()
     print "Joined domain %s (SID %s) as a DC" % (ctx.domain_name, ctx.domsid)
+
+def join_subdomain(server=None, creds=None, lp=None, site=None, netbios_name=None,
+                   targetdir=None, parent_domain=None, dnsdomain=None, netbios_domain=None):
+    """join as a DC"""
+    ctx = dc_join(server, creds, lp, site, netbios_name, targetdir, parent_domain)
+    ctx.subdomain = True
+    ctx.domain_name = netbios_domain
+    ctx.realm = dnsdomain
+    ctx.dnsdomain = dnsdomain
+    ctx.base_dn = samba.dn_from_dns_name(dnsdomain)
+    ctx.domsid = str(security.random_sid())
+    ctx.acct_dn = None
+    ctx.dnshostname = "%s.%s" % (ctx.myname, ctx.dnsdomain)
+
+    ctx.userAccountControl = samba.dsdb.UF_SERVER_TRUST_ACCOUNT | samba.dsdb.UF_TRUSTED_FOR_DELEGATION
+
+    ctx.SPNs.append('E3514235-4B06-11D1-AB04-00C04FC2DCD2/$NTDSGUID/%s' % ctx.dnsdomain)
+    ctx.secure_channel_type = misc.SEC_CHAN_BDC
+
+    ctx.replica_flags = (drsuapi.DRSUAPI_DRS_WRIT_REP |
+                         drsuapi.DRSUAPI_DRS_INIT_SYNC |
+                         drsuapi.DRSUAPI_DRS_PER_SYNC |
+                         drsuapi.DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS |
+                         drsuapi.DRSUAPI_DRS_NEVER_SYNCED)
+    ctx.domain_replica_flags = ctx.replica_flags
+
+    ctx.do_join()
+    print "Created domain %s (SID %s) as a DC" % (ctx.domain_name, ctx.domsid)
index b8f5561552f6be7cad19153811cdba76c4310d7f..94900014041fb5010172ccdd105b81ad54c7bb4b 100644 (file)
@@ -31,7 +31,7 @@ import logging
 from samba import Ldb
 from samba.net import Net, LIBNET_JOIN_AUTOMATIC
 from samba.dcerpc.misc import SEC_CHAN_WKSTA
-from samba.join import join_RODC, join_DC
+from samba.join import join_RODC, join_DC, join_subdomain
 from samba.auth import system_session
 from samba.samdb import SamDB
 from samba.dcerpc.samr import DOMAIN_PASSWORD_COMPLEX, DOMAIN_PASSWORD_STORE_CLEARTEXT
@@ -76,12 +76,13 @@ class cmd_domain_export_keytab(Command):
 class cmd_domain_join(Command):
     """Joins domain as either member or backup domain controller *"""
 
-    synopsis = "%prog domain join <dnsdomain> [DC|RODC|MEMBER] [options]"
+    synopsis = "%prog domain join <dnsdomain> [DC|RODC|MEMBER|SUBDOMAIN] [options]"
 
     takes_options = [
         Option("--server", help="DC to join", type=str),
         Option("--site", help="site to join", type=str),
         Option("--targetdir", help="where to store provision", type=str),
+        Option("--parent-domain", help="parent domain to create subdomain under", type=str),
         Option("--domain-critical-only",
                help="only replicate critical domain objects",
                action="store_true"),
@@ -91,7 +92,7 @@ class cmd_domain_join(Command):
 
     def run(self, domain, role=None, sambaopts=None, credopts=None,
             versionopts=None, server=None, site=None, targetdir=None,
-            domain_critical_only=False):
+            domain_critical_only=False, parent_domain=None):
         lp = sambaopts.get_loadparm()
         creds = credopts.get_credentials(lp)
         net = Net(creds, lp, server=credopts.ipaddress)
@@ -121,6 +122,13 @@ class cmd_domain_join(Command):
                       site=site, netbios_name=netbios_name, targetdir=targetdir,
                       domain_critical_only=domain_critical_only)
             return
+        elif role == "SUBDOMAIN":
+            netbios_domain = lp.get("workgroup")
+            if parent_domain is None:
+                parent_domain = ".".join(domain.split(".")[1:])
+            join_subdomain(server=server, creds=creds, lp=lp, dnsdomain=domain, parent_domain=parent_domain,
+                           site=site, netbios_name=netbios_name, netbios_domain=netbios_domain, targetdir=targetdir)
+            return
         else:
             raise CommandError("Invalid role %s (possible values: MEMBER, DC, RODC)" % role)
 
index 9f49f44952476bce1755bf1fb1f5605b289766a9..130ea72e70a626e1ea1efe651b3ca5bca785c63f 100644 (file)
@@ -438,6 +438,7 @@ class ProvisionResult(object):
         self.lp = None
         self.samdb = None
         self.idmap = None
+        self.names = None
 
 
 def check_install(lp, session_info, credentials):
@@ -761,7 +762,7 @@ def make_smbconf(smbconf, hostname, domain, realm, serverrole,
 
 
 
-def setup_name_mappings(samdb, idmap, sid, domaindn, root_uid, nobody_uid,
+def setup_name_mappings(idmap, sid, root_uid, nobody_uid,
                         users_gid, wheel_gid):
     """setup reasonable name mappings for sam names to unix names.
 
@@ -1064,7 +1065,7 @@ def setup_samdb_rootdse(samdb, names):
         })
 
 
-def setup_self_join(samdb, names, machinepass, dnspass,
+def setup_self_join(samdb, names, fill, machinepass, dnspass,
                     domainsid, next_rid, invocationid,
                     policyguid, policyguid_dc, domainControllerFunctionality,
                     ntdsguid, dc_rid=None):
@@ -1100,18 +1101,35 @@ def setup_self_join(samdb, names, machinepass, dnspass,
               "DNSDOMAIN": names.dnsdomain,
               "DOMAINDN": names.domaindn})
 
-    # add the NTDSGUID based SPNs
-    ntds_dn = "CN=NTDS Settings,%s" % names.serverdn
-    names.ntdsguid = samdb.searchone(basedn=ntds_dn, attribute="objectGUID",
-                                     expression="", scope=ldb.SCOPE_BASE)
-    assert isinstance(names.ntdsguid, str)
+    # If we are setting up a subdomain, then this has been replicated in, so we don't need to add it
+    if fill == FILL_FULL:
+        setup_add_ldif(samdb, setup_path("provision_self_join_config.ldif"), {
+                "CONFIGDN": names.configdn,
+                "SCHEMADN": names.schemadn,
+                "DOMAINDN": names.domaindn,
+                "SERVERDN": names.serverdn,
+                "INVOCATIONID": invocationid,
+                "NETBIOSNAME": names.netbiosname,
+                "DNSNAME": "%s.%s" % (names.hostname, names.dnsdomain),
+                "MACHINEPASS_B64": b64encode(machinepass.encode('utf-16-le')),
+                "DOMAINSID": str(domainsid),
+                "DCRID": str(dc_rid),
+                "SAMBA_VERSION_STRING": version,
+                "NTDSGUID": ntdsguid_line,
+                "DOMAIN_CONTROLLER_FUNCTIONALITY": str(
+                    domainControllerFunctionality)})
+
+    # Setup fSMORoleOwner entries to point at the newly created DC entry
+        setup_modify_ldif(samdb, setup_path("provision_self_join_modify_config.ldif"), {
+                "CONFIGDN": names.configdn,
+                "SCHEMADN": names.schemadn,
+                "DEFAULTSITE": names.sitename,
+                "SERVERDN": names.serverdn,
+                })
 
     # Setup fSMORoleOwner entries to point at the newly created DC entry
     setup_modify_ldif(samdb, setup_path("provision_self_join_modify.ldif"), {
               "DOMAINDN": names.domaindn,
-              "CONFIGDN": names.configdn,
-              "SCHEMADN": names.schemadn,
-              "DEFAULTSITE": names.sitename,
               "SERVERDN": names.serverdn,
               "NETBIOSNAME": names.netbiosname,
               "RIDALLOCATIONSTART": str(next_rid + 100),
@@ -1174,15 +1192,48 @@ def create_default_gpo(sysvolpath, dnsdomain, policyguid, policyguid_dc):
 
 
 def setup_samdb(path, session_info, provision_backend, lp, names,
-        logger, domainsid, domainguid, policyguid, policyguid_dc, fill,
-        adminpass, krbtgtpass, machinepass, invocationid, dnspass, ntdsguid,
-        serverrole, am_rodc=False, dom_for_fun_level=None, schema=None,
-        next_rid=None, dc_rid=None):
+        logger, fill, serverrole,
+        am_rodc=False, schema=None):
     """Setup a complete SAM Database.
 
     :note: This will wipe the main SAM database file!
     """
 
+    # Also wipes the database
+    setup_samdb_partitions(path, logger=logger, lp=lp,
+        provision_backend=provision_backend, session_info=session_info,
+        names=names, serverrole=serverrole, schema=schema)
+
+    if schema is None:
+        schema = Schema(domainsid, schemadn=names.schemadn)
+
+    # Load the database, but don's load the global schema and don't connect
+    # quite yet
+    samdb = SamDB(session_info=session_info, url=None, auto_connect=False,
+                  credentials=provision_backend.credentials, lp=lp,
+                  global_schema=False, am_rodc=am_rodc)
+
+    logger.info("Pre-loading the Samba 4 and AD schema")
+
+    # Load the schema from the one we computed earlier
+    samdb.set_schema(schema)
+
+    # Set the NTDS settings DN manually - in order to have it already around
+    # before the provisioned tree exists and we connect
+    samdb.set_ntds_settings_dn("CN=NTDS Settings,%s" % names.serverdn)
+
+    # And now we can connect to the DB - the schema won't be loaded from the
+    # DB
+    samdb.connect(path)
+
+    return samdb
+
+def fill_samdb(samdb, lp, names,
+        logger, domainsid, domainguid, policyguid, policyguid_dc, fill,
+        adminpass, krbtgtpass, machinepass, invocationid, dnspass, ntdsguid,
+        serverrole, am_rodc=False, dom_for_fun_level=None, schema=None,
+        next_rid=None, dc_rid=None):
+
     if next_rid is None:
         next_rid = 1000
 
@@ -1208,36 +1259,10 @@ def setup_samdb(path, session_info, provision_backend, lp, names,
     domainFunctionality = dom_for_fun_level
     forestFunctionality = dom_for_fun_level
 
-    # Also wipes the database
-    setup_samdb_partitions(path, logger=logger, lp=lp,
-        provision_backend=provision_backend, session_info=session_info,
-        names=names, serverrole=serverrole, schema=schema)
-
-    if schema is None:
-        schema = Schema(domainsid, schemadn=names.schemadn)
-
-    # Load the database, but don's load the global schema and don't connect
-    # quite yet
-    samdb = SamDB(session_info=session_info, url=None, auto_connect=False,
-                  credentials=provision_backend.credentials, lp=lp,
-                  global_schema=False, am_rodc=am_rodc)
-
-    logger.info("Pre-loading the Samba 4 and AD schema")
-
-    # Load the schema from the one we computed earlier
-    samdb.set_schema(schema)
-
     # Set the NTDS settings DN manually - in order to have it already around
     # before the provisioned tree exists and we connect
     samdb.set_ntds_settings_dn("CN=NTDS Settings,%s" % names.serverdn)
 
-    # And now we can connect to the DB - the schema won't be loaded from the
-    # DB
-    samdb.connect(path)
-
-    if fill == FILL_DRS:
-        return samdb
-
     samdb.transaction_start()
     try:
         # Set the domain functionality levels onto the database.
@@ -1283,28 +1308,29 @@ def setup_samdb(path, session_info, provision_backend, lp, names,
             "SAMBA_VERSION_STRING": version
             })
 
-        logger.info("Adding configuration container")
-        descr = b64encode(get_config_descriptor(domainsid))
-        setup_add_ldif(samdb, setup_path("provision_configuration_basedn.ldif"), {
-            "CONFIGDN": names.configdn,
-            "DESCRIPTOR": descr,
-            })
+        # If we are setting up a subdomain, then this has been replicated in, so we don't need to add it
+        if fill == FILL_FULL:
+            logger.info("Adding configuration container")
+            descr = b64encode(get_config_descriptor(domainsid))
+            setup_add_ldif(samdb, setup_path("provision_configuration_basedn.ldif"), {
+                    "CONFIGDN": names.configdn,
+                    "DESCRIPTOR": descr,
+                    })
+
+            # The LDIF here was created when the Schema object was constructed
+            logger.info("Setting up sam.ldb schema")
+            samdb.add_ldif(schema.schema_dn_add, controls=["relax:0"])
+            samdb.modify_ldif(schema.schema_dn_modify)
+            samdb.write_prefixes_from_schema()
+            samdb.add_ldif(schema.schema_data, controls=["relax:0"])
+            setup_add_ldif(samdb, setup_path("aggregate_schema.ldif"),
+                           {"SCHEMADN": names.schemadn})
 
         # Now register this container in the root of the forest
         msg = ldb.Message(ldb.Dn(samdb, names.domaindn))
         msg["subRefs"] = ldb.MessageElement(names.configdn , ldb.FLAG_MOD_ADD,
                     "subRefs")
 
-        # The LDIF here was created when the Schema object was constructed
-        logger.info("Setting up sam.ldb schema")
-        samdb.add_ldif(schema.schema_dn_add, controls=["relax:0"])
-        samdb.modify_ldif(schema.schema_dn_modify)
-        samdb.write_prefixes_from_schema()
-        samdb.add_ldif(schema.schema_data, controls=["relax:0"])
-        setup_add_ldif(samdb, setup_path("aggregate_schema.ldif"),
-                       {"SCHEMADN": names.schemadn})
-
-        logger.info("Reopening sam.ldb with new schema")
     except Exception:
         samdb.transaction_cancel()
         raise
@@ -1324,27 +1350,29 @@ def setup_samdb(path, session_info, provision_backend, lp, names,
     try:
         samdb.invocation_id = invocationid
 
-        logger.info("Setting up sam.ldb configuration data")
-        setup_add_ldif(samdb, setup_path("provision_configuration.ldif"), {
-            "CONFIGDN": names.configdn,
-            "NETBIOSNAME": names.netbiosname,
-            "DEFAULTSITE": names.sitename,
-            "DNSDOMAIN": names.dnsdomain,
-            "DOMAIN": names.domain,
-            "SCHEMADN": names.schemadn,
-            "DOMAINDN": names.domaindn,
-            "SERVERDN": names.serverdn,
-            "FOREST_FUNCTIONALITY": str(forestFunctionality),
-            "DOMAIN_FUNCTIONALITY": str(domainFunctionality),
-            })
+        # If we are setting up a subdomain, then this has been replicated in, so we don't need to add it
+        if fill == FILL_FULL:
+            logger.info("Setting up sam.ldb configuration data")
+            setup_add_ldif(samdb, setup_path("provision_configuration.ldif"), {
+                    "CONFIGDN": names.configdn,
+                    "NETBIOSNAME": names.netbiosname,
+                    "DEFAULTSITE": names.sitename,
+                    "DNSDOMAIN": names.dnsdomain,
+                    "DOMAIN": names.domain,
+                    "SCHEMADN": names.schemadn,
+                    "DOMAINDN": names.domaindn,
+                    "SERVERDN": names.serverdn,
+                    "FOREST_FUNCTIONALITY": str(forestFunctionality),
+                    "DOMAIN_FUNCTIONALITY": str(domainFunctionality),
+                    })
 
-        logger.info("Setting up display specifiers")
-        display_specifiers_ldif = read_ms_ldif(
-            setup_path('display-specifiers/DisplaySpecifiers-Win2k8R2.txt'))
-        display_specifiers_ldif = substitute_var(display_specifiers_ldif,
-            {"CONFIGDN": names.configdn})
-        check_all_substituted(display_specifiers_ldif)
-        samdb.add_ldif(display_specifiers_ldif)
+            logger.info("Setting up display specifiers")
+            display_specifiers_ldif = read_ms_ldif(
+                setup_path('display-specifiers/DisplaySpecifiers-Win2k8R2.txt'))
+            display_specifiers_ldif = substitute_var(display_specifiers_ldif,
+                                                     {"CONFIGDN": names.configdn})
+            check_all_substituted(display_specifiers_ldif)
+            samdb.add_ldif(display_specifiers_ldif)
 
         logger.info("Adding users container")
         setup_add_ldif(samdb, setup_path("provision_users_add.ldif"), {
@@ -1371,15 +1399,17 @@ def setup_samdb(path, session_info, provision_backend, lp, names,
             "POLICYGUID_DC": policyguid_dc
             })
 
-        setup_modify_ldif(samdb,
-            setup_path("provision_basedn_references.ldif"), {
-                "DOMAINDN": names.domaindn})
+        # If we are setting up a subdomain, then this has been replicated in, so we don't need to add it
+        if fill == FILL_FULL:
+            setup_modify_ldif(samdb,
+                              setup_path("provision_basedn_references.ldif"),
+                              {"DOMAINDN": names.domaindn})
 
         setup_modify_ldif(samdb,
             setup_path("provision_configuration_references.ldif"), {
                 "CONFIGDN": names.configdn,
                 "SCHEMADN": names.schemadn})
-        if fill == FILL_FULL:
+        if fill == FILL_FULL or fill == FILL_SUBDOMAIN:
             logger.info("Setting up sam.ldb users and groups")
             setup_add_ldif(samdb, setup_path("provision_users.ldif"), {
                 "DOMAINDN": names.domaindn,
@@ -1390,7 +1420,7 @@ def setup_samdb(path, session_info, provision_backend, lp, names,
                 })
 
             logger.info("Setting up self join")
-            setup_self_join(samdb, names=names, invocationid=invocationid,
+            setup_self_join(samdb, names=names, fill=fill, invocationid=invocationid,
                             dnspass=dnspass,
                             machinepass=machinepass,
                             domainsid=domainsid,
@@ -1414,6 +1444,7 @@ def setup_samdb(path, session_info, provision_backend, lp, names,
 
 
 FILL_FULL = "FULL"
+FILL_SUBDOMAIN = "SUBDOMAIN"
 FILL_NT4SYNC = "NT4SYNC"
 FILL_DRS = "DRS"
 SYSVOL_ACL = "O:LAG:BAD:P(A;OICI;0x001f01ff;;;BA)(A;OICI;0x001200a9;;;SO)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)"
@@ -1512,30 +1543,16 @@ def interface_ips_v6(lp, linklocal=False):
     return ret
 
 
-def provision(logger, session_info, credentials, smbconf=None,
-        targetdir=None, samdb_fill=FILL_FULL, realm=None, rootdn=None,
-        domaindn=None, schemadn=None, configdn=None, serverdn=None,
-        domain=None, hostname=None, hostip=None, hostip6=None, domainsid=None,
-        next_rid=1000, dc_rid=None, adminpass=None, ldapadminpass=None, krbtgtpass=None,
-        domainguid=None, policyguid=None, policyguid_dc=None,
-        invocationid=None, machinepass=None, ntdsguid=None,
-        dns_backend=None, dnspass=None,
-        root=None, nobody=None, users=None, wheel=None, backup=None, aci=None,
-        serverrole=None, dom_for_fun_level=None, ldap_backend_extra_port=None,
-        ldap_backend_forced_uri=None, backend_type=None, sitename=None,
-        ol_mmr_urls=None, ol_olc=None, setup_ds_path=None, slapd_path=None,
-        nosync=False, ldap_dryrun_mode=False, useeadb=False, am_rodc=False,
-        lp=None):
-    """Provision samba4
-
-    :note: caution, this wipes all existing data!
-    """
-
-    if domainsid is None:
-        domainsid = security.random_sid()
-    else:
-        domainsid = security.dom_sid(domainsid)
-
+def provision_fill(samdb, secrets_ldb, logger, names, paths,
+                   domainsid, schema=None,
+                   targetdir=None, samdb_fill=FILL_FULL,
+                   hostip=None, hostip6=None,
+                   next_rid=1000, dc_rid=None, adminpass=None, krbtgtpass=None,
+                   domainguid=None, policyguid=None, policyguid_dc=None,
+                   invocationid=None, machinepass=None, ntdsguid=None,
+                   dns_backend=None, dnspass=None,
+                   serverrole=None, dom_for_fun_level=None,
+                   am_rodc=False, lp=None):
     # create/adapt the group policy GUIDs
     # Default GUID for default policy are described at
     # "How Core Group Policy Works"
@@ -1547,6 +1564,9 @@ def provision(logger, session_info, credentials, smbconf=None,
         policyguid_dc = DEFAULT_DC_POLICY_GUID
     policyguid_dc = policyguid_dc.upper()
 
+    if invocationid is None:
+        invocationid = str(uuid.uuid4())
+
     if adminpass is None:
         adminpass = samba.generate_random_password(12, 32)
     if krbtgtpass is None:
@@ -1555,6 +1575,135 @@ def provision(logger, session_info, credentials, smbconf=None,
         machinepass  = samba.generate_random_password(128, 255)
     if dnspass is None:
         dnspass = samba.generate_random_password(128, 255)
+
+    samdb = fill_samdb(samdb, lp, names, logger=logger,
+                       domainsid=domainsid, schema=schema, domainguid=domainguid,
+                       policyguid=policyguid, policyguid_dc=policyguid_dc,
+                       fill=samdb_fill, adminpass=adminpass, krbtgtpass=krbtgtpass,
+                       invocationid=invocationid, machinepass=machinepass,
+                       dnspass=dnspass, ntdsguid=ntdsguid, serverrole=serverrole,
+                       dom_for_fun_level=dom_for_fun_level, am_rodc=am_rodc,
+                       next_rid=next_rid, dc_rid=dc_rid)
+
+    if serverrole == "domain controller":
+        # Set up group policies (domain policy and domain controller
+        # policy)
+        create_default_gpo(paths.sysvol, names.dnsdomain, policyguid,
+                           policyguid_dc)
+        setsysvolacl(samdb, paths.netlogon, paths.sysvol, paths.wheel_gid,
+                     domainsid, names.dnsdomain, names.domaindn, lp)
+
+        logger.info("Setting up sam.ldb rootDSE marking as synchronized")
+        setup_modify_ldif(samdb, setup_path("provision_rootdse_modify.ldif"),
+                          { 'NTDSGUID' : names.ntdsguid })
+
+        secretsdb_self_join(secrets_ldb, domain=names.domain,
+                            realm=names.realm, dnsdomain=names.dnsdomain,
+                            netbiosname=names.netbiosname, domainsid=domainsid,
+                            machinepass=machinepass, secure_channel_type=SEC_CHAN_BDC)
+
+        # Now set up the right msDS-SupportedEncryptionTypes into the DB
+        # In future, this might be determined from some configuration
+        kerberos_enctypes = str(ENC_ALL_TYPES)
+
+        try:
+            msg = ldb.Message(ldb.Dn(samdb,
+                                     samdb.searchone("distinguishedName",
+                                                     expression="samAccountName=%s$" % names.netbiosname,
+                                                     scope=ldb.SCOPE_SUBTREE)))
+            msg["msDS-SupportedEncryptionTypes"] = ldb.MessageElement(
+                elements=kerberos_enctypes, flags=ldb.FLAG_MOD_REPLACE,
+                name="msDS-SupportedEncryptionTypes")
+            samdb.modify(msg)
+        except ldb.LdbError, (enum, estr):
+            if enum != ldb.ERR_NO_SUCH_ATTRIBUTE:
+                # It might be that this attribute does not exist in this schema
+                raise
+
+        if serverrole == "domain controller":
+            secretsdb_setup_dns(secrets_ldb, names,
+                                paths.private_dir, realm=names.realm,
+                                dnsdomain=names.dnsdomain,
+                                dns_keytab_path=paths.dns_keytab, dnspass=dnspass)
+
+            # Default DNS backend is BIND9 using txt files for zone information
+            if not dns_backend:
+                dns_backend = "BIND9"
+
+            setup_ad_dns(samdb, names, logger, hostip=hostip, hostip6=hostip6,
+                         dns_backend=dns_backend, os_level=dom_for_fun_level)
+
+            domainguid = samdb.searchone(basedn=samdb.get_default_basedn(),
+                                         attribute="objectGUID")
+            assert isinstance(domainguid, str)
+
+            create_dns_dir(logger, paths)
+
+            # Only make a zone file on the first DC, it should be
+            # replicated with DNS replication
+            if dns_backend == "BIND9":
+                create_zone_file(lp, logger, paths, targetdir,
+                                 dnsdomain=names.dnsdomain, hostip=hostip, hostip6=hostip6,
+                                 hostname=names.hostname, realm=names.realm,
+                                 domainguid=domainguid, ntdsguid=names.ntdsguid)
+
+            create_named_conf(paths, realm=names.realm,
+                              dnsdomain=names.dnsdomain, dns_backend=dns_backend)
+
+            create_named_txt(paths.namedtxt,
+                             realm=names.realm, dnsdomain=names.dnsdomain,
+                             dnsname = "%s.%s" % (names.hostname, names.dnsdomain),
+                             private_dir=paths.private_dir,
+                             keytab_name=paths.dns_keytab)
+            logger.info("See %s for an example configuration include file for BIND", paths.namedconf)
+            logger.info("and %s for further documentation required for secure DNS "
+                        "updates", paths.namedtxt)
+
+            lastProvisionUSNs = get_last_provision_usn(samdb)
+            maxUSN = get_max_usn(samdb, str(names.rootdn))
+            if lastProvisionUSNs is not None:
+                update_provision_usn(samdb, 0, maxUSN, invocationid, 1)
+            else:
+                set_provision_usn(samdb, 0, maxUSN, invocationid)
+
+        # fix any dangling GUIDs from the provision
+        logger.info("Fixing provision GUIDs")
+        chk = dbcheck(samdb, samdb_schema=samdb,  verbose=False, fix=True, yes=True, quiet=True)
+        samdb.transaction_start()
+        # a small number of GUIDs are missing because of ordering issues in the
+        # provision code
+        for schema_obj in ['CN=Domain', 'CN=Organizational-Person', 'CN=Contact', 'CN=inetOrgPerson']:
+            chk.check_database(DN="%s,%s" % (schema_obj, names.schemadn),
+                               scope=ldb.SCOPE_BASE, attrs=['defaultObjectCategory'])
+        chk.check_database(DN="CN=IP Security,CN=System,%s" % names.domaindn,
+                           scope=ldb.SCOPE_ONELEVEL,
+                           attrs=['ipsecOwnersReference',
+                                  'ipsecFilterReference',
+                                  'ipsecISAKMPReference',
+                                  'ipsecNegotiationPolicyReference',
+                                  'ipsecNFAReference'])
+        samdb.transaction_commit()
+
+
+def provision(logger, session_info, credentials, smbconf=None,
+        targetdir=None, samdb_fill=FILL_FULL, realm=None, rootdn=None,
+        domaindn=None, schemadn=None, configdn=None, serverdn=None,
+        domain=None, hostname=None, hostip=None, hostip6=None, domainsid=None,
+        next_rid=1000, dc_rid=None, adminpass=None, ldapadminpass=None, krbtgtpass=None,
+        domainguid=None, policyguid=None, policyguid_dc=None,
+        dns_backend=None, dnspass=None,
+        invocationid=None, machinepass=None, ntdsguid=None,
+        root=None, nobody=None, users=None, wheel=None, backup=None, aci=None,
+        serverrole=None, dom_for_fun_level=None, ldap_backend_extra_port=None,
+        ldap_backend_forced_uri=None, backend_type=None, sitename=None,
+        ol_mmr_urls=None, ol_olc=None, setup_ds_path=None, slapd_path=None,
+        nosync=False, ldap_dryrun_mode=False, useeadb=False, am_rodc=False,
+        lp=None):
+    """Provision samba4
+
+    :note: caution, this wipes all existing data!
+    """
+
     if ldapadminpass is None:
         # Make a new, random password between Samba and it's LDAP server
         ldapadminpass=samba.generate_random_password(128, 255)
@@ -1562,6 +1711,11 @@ def provision(logger, session_info, credentials, smbconf=None,
     if backend_type is None:
         backend_type = "ldb"
 
+    if domainsid is None:
+        domainsid = security.random_sid()
+    else:
+        domainsid = security.dom_sid(domainsid)
+
     sid_generator = "internal"
     if backend_type == "fedora-ds":
         sid_generator = "backend"
@@ -1610,6 +1764,7 @@ def provision(logger, session_info, credentials, smbconf=None,
     paths = provision_paths_from_lp(lp, names.dnsdomain)
 
     paths.bind_gid = bind_gid
+    paths.wheel_gid = wheel_gid
 
     if hostip is None:
         logger.info("Looking up IPv4 addresses")
@@ -1638,8 +1793,6 @@ def provision(logger, session_info, credentials, smbconf=None,
         serverrole = lp.get("server role")
 
     assert serverrole in ("domain controller", "member server", "standalone")
-    if invocationid is None:
-        invocationid = str(uuid.uuid4())
 
     if not os.path.exists(paths.private_dir):
         os.mkdir(paths.private_dir)
@@ -1710,16 +1863,15 @@ def provision(logger, session_info, credentials, smbconf=None,
         idmap = setup_idmapdb(paths.idmapdb,
             session_info=session_info, lp=lp)
 
+        setup_name_mappings(idmap, sid=str(domainsid),
+                            root_uid=root_uid, nobody_uid=nobody_uid,
+                            users_gid=users_gid, wheel_gid=wheel_gid)
+
         logger.info("Setting up SAM db")
         samdb = setup_samdb(paths.samdb, session_info,
-            provision_backend, lp, names, logger=logger,
-            domainsid=domainsid, schema=schema, domainguid=domainguid,
-            policyguid=policyguid, policyguid_dc=policyguid_dc,
-            fill=samdb_fill, adminpass=adminpass, krbtgtpass=krbtgtpass,
-            invocationid=invocationid, machinepass=machinepass,
-            dnspass=dnspass, ntdsguid=ntdsguid, serverrole=serverrole,
-            dom_for_fun_level=dom_for_fun_level, am_rodc=am_rodc,
-            next_rid=next_rid, dc_rid=dc_rid)
+                            provision_backend, lp, names, logger=logger,
+                            serverrole=serverrole,
+                            schema=schema, fill=samdb_fill, am_rodc=am_rodc)
 
         if serverrole == "domain controller":
             if paths.netlogon is None:
@@ -1739,90 +1891,16 @@ def provision(logger, session_info, credentials, smbconf=None,
                 os.makedirs(paths.netlogon, 0755)
 
         if samdb_fill == FILL_FULL:
-            setup_name_mappings(samdb, idmap, str(domainsid), names.domaindn,
-                                root_uid=root_uid, nobody_uid=nobody_uid,
-                                users_gid=users_gid, wheel_gid=wheel_gid)
-
-            if serverrole == "domain controller":
-                # Set up group policies (domain policy and domain controller
-                # policy)
-                create_default_gpo(paths.sysvol, names.dnsdomain, policyguid,
-                    policyguid_dc)
-                setsysvolacl(samdb, paths.netlogon, paths.sysvol, wheel_gid,
-                    domainsid, names.dnsdomain, names.domaindn, lp)
-
-            logger.info("Setting up sam.ldb rootDSE marking as synchronized")
-            setup_modify_ldif(samdb, setup_path("provision_rootdse_modify.ldif"),
-                              { 'NTDSGUID' : names.ntdsguid })
-
-            secretsdb_self_join(secrets_ldb, domain=names.domain,
-                realm=names.realm, dnsdomain=names.dnsdomain,
-                netbiosname=names.netbiosname, domainsid=domainsid,
-                machinepass=machinepass, secure_channel_type=SEC_CHAN_BDC)
-
-            # Now set up the right msDS-SupportedEncryptionTypes into the DB
-            # In future, this might be determined from some configuration
-            kerberos_enctypes = str(ENC_ALL_TYPES)
-
-            try:
-                msg = ldb.Message(ldb.Dn(samdb,
-                    samdb.searchone("distinguishedName",
-                        expression="samAccountName=%s$" % names.netbiosname,
-                        scope=ldb.SCOPE_SUBTREE)))
-                msg["msDS-SupportedEncryptionTypes"] = ldb.MessageElement(
-                    elements=kerberos_enctypes, flags=ldb.FLAG_MOD_REPLACE,
-                    name="msDS-SupportedEncryptionTypes")
-                samdb.modify(msg)
-            except ldb.LdbError, (enum, estr):
-                if enum != ldb.ERR_NO_SUCH_ATTRIBUTE:
-                    # It might be that this attribute does not exist in this schema
-                    raise
-
-            if serverrole == "domain controller":
-                secretsdb_setup_dns(secrets_ldb, names,
-                    paths.private_dir, realm=names.realm,
-                    dnsdomain=names.dnsdomain,
-                    dns_keytab_path=paths.dns_keytab, dnspass=dnspass)
-
-                # Default DNS backend is BIND9 using txt files for zone information 
-                if not dns_backend:
-                    dns_backend = "BIND9"
-
-                setup_ad_dns(samdb, names, logger, hostip=hostip, hostip6=hostip6,
-                            dns_backend=dns_backend, os_level=dom_for_fun_level)
-
-                domainguid = samdb.searchone(basedn=domaindn,
-                    attribute="objectGUID")
-                assert isinstance(domainguid, str)
-
-                create_dns_dir(logger, paths)
-
-                # Only make a zone file on the first DC, it should be
-                # replicated with DNS replication
-                if dns_backend == "BIND9":
-                    create_zone_file(lp, logger, paths, targetdir,
-                        dnsdomain=names.dnsdomain, hostip=hostip, hostip6=hostip6,
-                        hostname=names.hostname, realm=names.realm,
-                        domainguid=domainguid, ntdsguid=names.ntdsguid)
-
-                create_named_conf(paths, realm=names.realm,
-                    dnsdomain=names.dnsdomain, dns_backend=dns_backend)
-
-                create_named_txt(paths.namedtxt,
-                    realm=names.realm, dnsdomain=names.dnsdomain,
-                    dnsname = "%s.%s" % (names.hostname, names.dnsdomain),
-                    private_dir=paths.private_dir,
-                    keytab_name=paths.dns_keytab)
-                logger.info("See %s for an example configuration include file for BIND", paths.namedconf)
-                logger.info("and %s for further documentation required for secure DNS "
-                        "updates", paths.namedtxt)
-
-            lastProvisionUSNs = get_last_provision_usn(samdb)
-            maxUSN = get_max_usn(samdb, str(names.rootdn))
-            if lastProvisionUSNs is not None:
-                update_provision_usn(samdb, 0, maxUSN, invocationid, 1)
-            else:
-                set_provision_usn(samdb, 0, maxUSN, invocationid)
+            provision_fill(samdb, secrets_ldb, logger,
+                           names, paths, schema=schema, targetdir=targetdir,
+                           samdb_fill=samdb_fill, hostip=hostip, hostip6=hostip6, domainsid=domainsid,
+                           next_rid=next_rid, dc_rid=dc_rid, adminpass=adminpass,
+                           krbtgtpass=krbtgtpass, domainguid=domainguid,
+                           policyguid=policyguid, policyguid_dc=policyguid_dc,
+                           invocationid=invocationid, machinepass=machinepass,
+                           ntdsguid=ntdsguid, dns_backend=dns_backend, dnspass=dnspass,
+                           serverrole=serverrole, dom_for_fun_level=dom_for_fun_level,
+                           am_rodc=am_rodc, lp=lp)
 
         create_krb5_conf(paths.krb5conf,
                          dnsdomain=names.dnsdomain, hostname=names.hostname,
@@ -1856,26 +1934,6 @@ def provision(logger, session_info, credentials, smbconf=None,
                 logger.info("Failed to chown %s to bind gid %u",
                             dns_keytab_path, paths.bind_gid)
 
-    if samdb_fill != FILL_DRS:
-        # fix any dangling GUIDs from the provision
-        logger.info("Fixing provision GUIDs")
-        chk = dbcheck(samdb, samdb_schema=samdb,  verbose=False, fix=True, yes=True, quiet=True)
-        samdb.transaction_start()
-        # a small number of GUIDs are missing because of ordering issues in the
-        # provision code
-        for schema_obj in ['CN=Domain', 'CN=Organizational-Person', 'CN=Contact', 'CN=inetOrgPerson']:
-            chk.check_database(DN="%s,%s" % (schema_obj, names.schemadn),
-                               scope=ldb.SCOPE_BASE, attrs=['defaultObjectCategory'])
-        chk.check_database(DN="CN=IP Security,CN=System,%s" % names.domaindn,
-                           scope=ldb.SCOPE_ONELEVEL,
-                           attrs=['ipsecOwnersReference',
-                                  'ipsecFilterReference',
-                                  'ipsecISAKMPReference',
-                                  'ipsecNegotiationPolicyReference',
-                                  'ipsecNFAReference'])
-        samdb.transaction_commit()
-
-
     logger.info("Please install the phpLDAPadmin configuration located at %s into /etc/phpldapadmin/config.php",
             paths.phpldapadminconfig)
 
@@ -1909,6 +1967,7 @@ def provision(logger, session_info, credentials, smbconf=None,
     result = ProvisionResult()
     result.domaindn = domaindn
     result.paths = paths
+    result.names = names
     result.lp = lp
     result.samdb = samdb
     result.idmap = idmap
index 9124ab50ef65e8cc49debefc3604556334b38e09..b19db78b72e47732ea3d5591fe6e043130f08446 100644 (file)
@@ -20,38 +20,3 @@ sAMAccountName: ${NETBIOSNAME}$
 userAccountControl: 532480
 clearTextPassword:: ${MACHINEPASS_B64}
 objectSid: ${DOMAINSID}-${DCRID}
-
-# Here are missing the objects for the NTFRS subscription since we don't
-# support this technique yet.
-
-# Objects under "Configuration/Sites/<Default sitename>/Servers"
-
-dn: ${SERVERDN}
-objectClass: top
-objectClass: server
-systemFlags: 1375731712
-dNSHostName: ${DNSNAME}
-serverReference: CN=${NETBIOSNAME},OU=Domain Controllers,${DOMAINDN}
-
-dn: CN=NTDS Settings,${SERVERDN}
-objectClass: top
-objectClass: applicationSettings
-objectClass: nTDSDSA
-dMDLocation: ${SCHEMADN}
-hasMasterNCs: ${CONFIGDN}
-hasMasterNCs: ${SCHEMADN}
-hasMasterNCs: ${DOMAINDN}
-invocationId: ${INVOCATIONID}
-msDS-Behavior-Version: ${DOMAIN_CONTROLLER_FUNCTIONALITY}
-msDS-HasDomainNCs: ${DOMAINDN}
-# "msDS-HasInstantiatedNCs"s for DNS is added from provision_dnszones_modify.ldif
-msDS-HasInstantiatedNCs: B:8:0000000D:${CONFIGDN}
-msDS-HasInstantiatedNCs: B:8:0000000D:${SCHEMADN}
-msDS-HasInstantiatedNCs: B:8:00000005:${DOMAINDN}
-# "msDS-hasMasterNCs"s for DNS is added from provision_dnszones_modify.ldif
-msDS-hasMasterNCs: ${CONFIGDN}
-msDS-hasMasterNCs: ${SCHEMADN}
-msDS-hasMasterNCs: ${DOMAINDN}
-options: 1
-systemFlags: 33554432
-${NTDSGUID}
diff --git a/source4/setup/provision_self_join_config.ldif b/source4/setup/provision_self_join_config.ldif
new file mode 100644 (file)
index 0000000..e0f1a5a
--- /dev/null
@@ -0,0 +1,33 @@
+# Here are missing the objects for the NTFRS subscription since we don't
+# support this technique yet.
+
+# Objects under "Configuration/Sites/<Default sitename>/Servers"
+
+dn: ${SERVERDN}
+objectClass: top
+objectClass: server
+systemFlags: 1375731712
+dNSHostName: ${DNSNAME}
+
+dn: CN=NTDS Settings,${SERVERDN}
+objectClass: top
+objectClass: applicationSettings
+objectClass: nTDSDSA
+dMDLocation: ${SCHEMADN}
+hasMasterNCs: ${CONFIGDN}
+hasMasterNCs: ${SCHEMADN}
+hasMasterNCs: ${DOMAINDN}
+invocationId: ${INVOCATIONID}
+msDS-Behavior-Version: ${DOMAIN_CONTROLLER_FUNCTIONALITY}
+msDS-HasDomainNCs: ${DOMAINDN}
+# "msDS-HasInstantiatedNCs"s for DNS is added from provision_dnszones_modify.ldif
+msDS-HasInstantiatedNCs: B:8:0000000D:${CONFIGDN}
+msDS-HasInstantiatedNCs: B:8:0000000D:${SCHEMADN}
+msDS-HasInstantiatedNCs: B:8:00000005:${DOMAINDN}
+# "msDS-hasMasterNCs"s for DNS is added from provision_dnszones_modify.ldif
+msDS-hasMasterNCs: ${CONFIGDN}
+msDS-hasMasterNCs: ${SCHEMADN}
+msDS-hasMasterNCs: ${DOMAINDN}
+options: 1
+systemFlags: 33554432
+${NTDSGUID}
index aba1b862e1b06760d477d57bcc0cc917c6ea50e8..7b5c562ed08ac1617ec2e8f5fe073ced21e59fe0 100644 (file)
@@ -5,11 +5,6 @@ fSMORoleOwner: CN=NTDS Settings,${SERVERDN}
 replace: rIDManagerReference
 rIDManagerReference: CN=RID Manager$,CN=System,${DOMAINDN}
 
-dn: ${SCHEMADN}
-changetype: modify
-replace: fSMORoleOwner
-fSMORoleOwner: CN=NTDS Settings,${SERVERDN}
-
 dn: CN=Infrastructure,${DOMAINDN}
 changetype: modify
 replace: fSMORoleOwner
@@ -20,16 +15,6 @@ changetype: modify
 replace: fSMORoleOwner
 fSMORoleOwner: CN=NTDS Settings,${SERVERDN}
 
-dn: CN=Partitions,${CONFIGDN}
-changetype: modify
-replace: fSMORoleOwner
-fSMORoleOwner: CN=NTDS Settings,${SERVERDN}
-
-dn: CN=NTDS Site Settings,CN=${DEFAULTSITE},CN=Sites,${CONFIGDN}
-changetype: modify
-replace: interSiteTopologyGenerator
-interSiteTopologyGenerator: CN=NTDS Settings,${SERVERDN}
-
 dn: CN=RID Set,CN=${NETBIOSNAME},OU=Domain Controllers,${DOMAINDN}
 changetype: add
 objectClass: rIDSet
@@ -42,3 +27,8 @@ dn: CN=${NETBIOSNAME},OU=Domain Controllers,${DOMAINDN}
 changetype: modify
 add: rIDSetReferences
 rIDSetReferences: CN=RID Set,CN=${NETBIOSNAME},OU=Domain Controllers,${DOMAINDN}
+
+dn: ${SERVERDN}
+changetype: modify
+add: serverReference
+serverReference: CN=${NETBIOSNAME},OU=Domain Controllers,${DOMAINDN}
diff --git a/source4/setup/provision_self_join_modify_config.ldif b/source4/setup/provision_self_join_modify_config.ldif
new file mode 100644 (file)
index 0000000..48a7092
--- /dev/null
@@ -0,0 +1,14 @@
+dn: ${SCHEMADN}
+changetype: modify
+replace: fSMORoleOwner
+fSMORoleOwner: CN=NTDS Settings,${SERVERDN}
+
+dn: CN=Partitions,${CONFIGDN}
+changetype: modify
+replace: fSMORoleOwner
+fSMORoleOwner: CN=NTDS Settings,${SERVERDN}
+
+dn: CN=NTDS Site Settings,CN=${DEFAULTSITE},CN=Sites,${CONFIGDN}
+changetype: modify
+replace: interSiteTopologyGenerator
+interSiteTopologyGenerator: CN=NTDS Settings,${SERVERDN}