s4:dsdb Add 'lazy_commit' module to swallow the 'lazy commit' OID
[ira/wip.git] / source4 / scripting / python / samba / provision.py
index 64491c2b18dcff3a81f557dcc3127dfa8ad77681..e830870bb093ec2e89c93ae2f790b8f063a870f9 100644 (file)
@@ -44,7 +44,7 @@ from credentials import Credentials, DONT_USE_KERBEROS
 from auth import system_session, admin_session
 from samba import version, Ldb, substitute_var, valid_netbios_name
 from samba import check_all_substituted
-from samba import DS_DOMAIN_FUNCTION_2000, DS_DOMAIN_FUNCTION_2008, DS_DC_FUNCTION_2008, DS_DC_FUNCTION_2008_R2
+from samba import DS_DOMAIN_FUNCTION_2003, DS_DOMAIN_FUNCTION_2008, DS_DC_FUNCTION_2008
 from samba.samdb import SamDB
 from samba.idmap import IDmapDB
 from samba.dcerpc import security
@@ -210,6 +210,8 @@ class Schema(object):
         prefixmap = open(setup_path("prefixMap.txt"), 'r').read()
         prefixmap = b64encode(prefixmap)
 
+        
+
         # We don't actually add this ldif, just parse it
         prefixmap_ldif = "dn: cn=schema\nprefixMap:: %s\n\n" % prefixmap
         self.ldb.set_schema_from_ldif(prefixmap_ldif, self.schema_data)
@@ -288,17 +290,17 @@ def read_and_sub_file(file, subst_vars):
     return data
 
 
-def setup_add_ldif(ldb, ldif_path, subst_vars=None):
+def setup_add_ldif(ldb, ldif_path, subst_vars=None,controls=["relax:0"]):
     """Setup a ldb in the private dir.
     
     :param ldb: LDB file to import data into
     :param ldif_path: Path of the LDIF file to load
     :param subst_vars: Optional variables to subsitute in LDIF.
+    :param nocontrols: Optional list of controls, can be None for no controls
     """
     assert isinstance(ldif_path, str)
-
     data = read_and_sub_file(ldif_path, subst_vars)
-    ldb.add_ldif(data)
+    ldb.add_ldif(data,controls)
 
 
 def setup_modify_ldif(ldb, ldif_path, subst_vars=None):
@@ -614,6 +616,7 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
     # - each partition has its own module list then
     modules_list = ["resolve_oids",
                     "rootdse",
+                    "lazy_commit",
                     "acl",
                     "paged_results",
                     "ranged_results",
@@ -874,9 +877,13 @@ def setup_samdb_rootdse(samdb, setup_path, names):
 def setup_self_join(samdb, names,
                     machinepass, dnspass, 
                     domainsid, invocationid, setup_path,
-                    policyguid, policyguid_dc, domainControllerFunctionality):
+                    policyguid, policyguid_dc, domainControllerFunctionality,ntdsguid):
     """Join a host to its own domain."""
     assert isinstance(invocationid, str)
+    if ntdsguid is not None:
+        ntdsguid_mod = "objectGUID: %s\n"%ntdsguid
+    else:
+        ntdsguid_mod = ""
     setup_add_ldif(samdb, setup_path("provision_self_join.ldif"), { 
               "CONFIGDN": names.configdn, 
               "SCHEMADN": names.schemadn,
@@ -892,6 +899,7 @@ def setup_self_join(samdb, names,
               "DOMAIN": names.domain,
               "DNSDOMAIN": names.dnsdomain,
               "SAMBA_VERSION_STRING": version,
+              "NTDSGUID": ntdsguid_mod,
               "DOMAIN_CONTROLLER_FUNCTIONALITY": str(domainControllerFunctionality)})
 
     setup_add_ldif(samdb, setup_path("provision_group_policy.ldif"), { 
@@ -925,23 +933,34 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
                 names, message, 
                 domainsid, domainguid, policyguid, policyguid_dc,
                 fill, adminpass, krbtgtpass, 
-                machinepass, invocationid, dnspass,
-                serverrole, schema=None, ldap_backend=None):
+                machinepass, invocationid, dnspass, ntdsguid,
+                serverrole, dom_for_fun_level=None,
+                schema=None, ldap_backend=None):
     """Setup a complete SAM Database.
     
     :note: This will wipe the main SAM database file!
     """
 
-    # Do NOT change these default values without discussion with the team and reslease manager.  
-    domainFunctionality = DS_DOMAIN_FUNCTION_2008
-    forestFunctionality = DS_DOMAIN_FUNCTION_2008
+    # ATTENTION: Do NOT change these default values without discussion with the
+    # team and/or release manager. They have a big impact on the whole program!
     domainControllerFunctionality = DS_DC_FUNCTION_2008
 
+    if dom_for_fun_level is None:
+        dom_for_fun_level = DS_DOMAIN_FUNCTION_2003
+    if dom_for_fun_level < DS_DOMAIN_FUNCTION_2003:
+        raise ProvisioningError("You want to run SAMBA 4 on a domain and forest function level lower than Windows 2003 (Native). This isn't supported!")
+
+    if dom_for_fun_level > domainControllerFunctionality:
+        raise ProvisioningError("You want to run SAMBA 4 on a domain and forest function level which itself is higher than its actual DC function level (2008). This won't work!")
+
+    domainFunctionality = dom_for_fun_level
+    forestFunctionality = dom_for_fun_level
+
     # Also wipes the database
     setup_samdb_partitions(path, setup_path, message=message, lp=lp,
                            credentials=credentials, session_info=session_info,
-                           names=names, 
-                           ldap_backend=ldap_backend, serverrole=serverrole)
+                           names=names, ldap_backend=ldap_backend,
+                           serverrole=serverrole)
 
     if (schema == None):
         schema = Schema(setup_path, domainsid, schemadn=names.schemadn, serverdn=names.serverdn,
@@ -997,17 +1016,16 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
 #impersonate domain admin
         admin_session_info = admin_session(lp, str(domainsid))
         samdb.set_session_info(admin_session_info)
-
+        if domainguid is not None:
+            domainguid_mod = "objectGUID: %s\n-" % domainguid
+        else:
+            domainguid_mod = ""
         setup_add_ldif(samdb, setup_path("provision_basedn.ldif"), {
                 "DOMAINDN": names.domaindn,
-                "DOMAIN_OC": domain_oc
+                "DOMAIN_OC": domain_oc,
+                "DOMAINGUID": domainguid_mod
                 })
 
-        message("Modifying DomainDN: " + names.domaindn + "")
-        if domainguid is not None:
-            domainguid_mod = "replace: objectGUID\nobjectGUID: %s\n-" % domainguid
-        else:
-            domainguid_mod = ""
 
         setup_modify_ldif(samdb, setup_path("provision_basedn_modify.ldif"), {
             "CREATTIME": str(int(time.time()) * 1e7), # seconds -> ticks
@@ -1019,7 +1037,6 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
             "SERVERDN": names.serverdn,
             "POLICYGUID": policyguid,
             "DOMAINDN": names.domaindn,
-            "DOMAINGUID_MOD": domainguid_mod,
             "DOMAIN_FUNCTIONALITY": str(domainFunctionality),
             "SAMBA_VERSION_STRING": version
             })
@@ -1038,10 +1055,10 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
 
         # The LDIF here was created when the Schema object was constructed
         message("Setting up sam.ldb schema")
-        samdb.add_ldif(schema.schema_dn_add)
+        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)
+        samdb.add_ldif(schema.schema_data, controls=["relax:0"])
         setup_add_ldif(samdb, setup_path("aggregate_schema.ldif"), 
                        {"SCHEMADN": names.schemadn})
 
@@ -1105,7 +1122,7 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
                                 domainsid=domainsid, policyguid=policyguid,
                                 policyguid_dc=policyguid_dc,
                                 setup_path=setup_path,
-                                domainControllerFunctionality=domainControllerFunctionality)
+                                domainControllerFunctionality=domainControllerFunctionality,ntdsguid=ntdsguid)
 
                 ntds_dn = "CN=NTDS Settings,CN=%s,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,%s" % (names.hostname, names.domaindn)
                 names.ntdsguid = samdb.searchone(basedn=ntds_dn,
@@ -1134,9 +1151,10 @@ def provision(setup_dir, message, session_info,
               domainsid=None, adminpass=None, ldapadminpass=None, 
               krbtgtpass=None, domainguid=None, 
               policyguid=None, policyguid_dc=None, invocationid=None,
-              machinepass=None, 
+              machinepass=None,ntdsguid=None,
               dnspass=None, root=None, nobody=None, users=None, 
-              wheel=None, backup=None, aci=None, serverrole=None, 
+              wheel=None, backup=None, aci=None, serverrole=None,
+              dom_for_fun_level=None,
               ldap_backend_extra_port=None, ldap_backend_type=None,
               sitename=None,
               ol_mmr_urls=None, ol_olc=None, 
@@ -1155,7 +1173,6 @@ def provision(setup_dir, message, session_info,
     else:
       domainsid = security.dom_sid(domainsid)
 
-
     # create/adapt the group policy GUIDs
     if policyguid is None:
         policyguid = str(uuid.uuid4())
@@ -1288,8 +1305,11 @@ def provision(setup_dir, message, session_info,
                         fill=samdb_fill, 
                         adminpass=adminpass, krbtgtpass=krbtgtpass,
                         invocationid=invocationid, 
-                        machinepass=machinepass, dnspass=dnspass,
-                        serverrole=serverrole, ldap_backend=provision_backend)
+                        machinepass=machinepass, dnspass=dnspass, 
+                        ntdsguid=ntdsguid,
+                        serverrole=serverrole,
+                        dom_for_fun_level=dom_for_fun_level,
+                        ldap_backend=provision_backend)
 
     if serverrole == "domain controller":
         if paths.netlogon is None: