s4:provison Add prefixes to ldb using same code a later modify will use
[ira/wip.git] / source4 / scripting / python / samba / provision.py
index bcb6566998eca1e8da20b0512b51679907c9eb93..a8cedaf23a6be4020aa2762a101edaecd07de0e0 100644 (file)
@@ -3,7 +3,7 @@
 # backend code for provisioning a Samba4 server
 
 # Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
-# Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
+# Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008-2009
 # Copyright (C) Oliver Liebel <oliver@itc.li> 2008-2009
 #
 # Based on the original in EJS:
@@ -39,7 +39,7 @@ import samba
 import subprocess
 
 import shutil
-from credentials import Credentials
+from credentials import Credentials, DONT_USE_KERBEROS
 from auth import system_session
 from samba import version, Ldb, substitute_var, valid_netbios_name, check_all_substituted, \
   DS_BEHAVIOR_WIN2008
@@ -151,18 +151,21 @@ class Schema(object):
         self.schema_data += open(setup_path("schema_samba4.ldif"), 'r').read()
         self.schema_data = substitute_var(self.schema_data, {"SCHEMADN": schemadn})
         check_all_substituted(self.schema_data)
-        prefixmap = open(setup_path("prefixMap.txt"), 'r').read()
-        prefixmap = b64encode(prefixmap)
-        
+
         self.schema_dn_modify = read_and_sub_file(setup_path("provision_schema_basedn_modify.ldif"),
                                                   {"SCHEMADN": schemadn,
-                                                   "PREFIXMAP_B64": prefixmap,
                                                    "SERVERDN": serverdn,
                                                    })
         self.schema_dn_add = read_and_sub_file(setup_path("provision_schema_basedn.ldif"),
                                                {"SCHEMADN": schemadn
                                                 })
-        self.ldb.set_schema_from_ldif(self.schema_dn_modify, self.schema_data)
+
+        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)
 
     
 def check_install(lp, session_info, credentials):
@@ -487,21 +490,18 @@ description: %s
         for msg in self.parse_ldif(add):
             self.add(msg[1])
 
-    # add some foreign sids
     add_foreign(samdb, domaindn, "S-1-5-7", "Anonymous")
     add_foreign(samdb, domaindn, "S-1-1-0", "World")
     add_foreign(samdb, domaindn, "S-1-5-2", "Network")
     add_foreign(samdb, domaindn, "S-1-5-18", "System")
     add_foreign(samdb, domaindn, "S-1-5-11", "Authenticated Users")
-
-
+    
     idmap.setup_name_mapping("S-1-5-7", idmap.TYPE_UID, nobody_uid)
     idmap.setup_name_mapping("S-1-5-32-544", idmap.TYPE_GID, wheel_gid)
-
+    
     idmap.setup_name_mapping(sid + "-500", idmap.TYPE_UID, root_uid)
     idmap.setup_name_mapping(sid + "-513", idmap.TYPE_GID, users_gid)
 
-
 def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info, 
                            credentials, names,
                            serverrole, ldap_backend=None, 
@@ -525,13 +525,13 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
         samdb = Ldb(url=samdb_path, session_info=session_info, 
                       credentials=credentials, lp=lp, options=["modules:"])
         # Wipes the database
-        samdb.erase()
+        samdb.erase_except_schema_controlled()
     except LdbError:
         os.unlink(samdb_path)
         samdb = Ldb(url=samdb_path, session_info=session_info, 
                       credentials=credentials, lp=lp, options=["modules:"])
          # Wipes the database
-        samdb.erase()
+        samdb.erase_except_schema_controlled()
         
 
     #Add modules to the list to activate them by default
@@ -790,12 +790,22 @@ def setup_self_join(samdb, names,
               "DNSDOMAIN": names.dnsdomain,
               "SAMBA_VERSION_STRING": version,
               "DOMAIN_CONTROLLER_FUNCTIONALITY": str(domainControllerFunctionality)})
+
     setup_add_ldif(samdb, setup_path("provision_group_policy.ldif"), { 
               "POLICYGUID": policyguid,
               "DNSDOMAIN": names.dnsdomain,
               "DOMAINSID": str(domainsid),
               "DOMAINDN": names.domaindn})
 
+    # 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
+              })
+
 
 def setup_samdb(path, setup_path, session_info, credentials, lp, 
                 names, message, 
@@ -818,6 +828,9 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
                            names=names, 
                            ldap_backend=ldap_backend, serverrole=serverrole)
 
+    if (schema == None):
+        schema = Schema(setup_path, schemadn=names.schemadn, serverdn=names.serverdn)
+
     # Load the database, but importantly, use Ldb not SamDB as we don't want to load the global schema
     samdb = Ldb(session_info=session_info, 
                 credentials=credentials, lp=lp)
@@ -835,10 +848,18 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
     samdb.transaction_start()
     try:
         message("Erasing data from partitions")
-        # Load the schema (again).  This time it will force a reindex, to make the below computationally sane
+        # Load the schema (again).  This time it will force a reindex,
+        # and will therefore make the erase_partitions() below
+        # computationally sane
         samdb.set_schema_from_ldb(schema.ldb)
         samdb.erase_partitions()
     
+        # Set the domain functionality levels onto the database.
+        # Various module (the password_hash module in particular) need
+        # to know what level of AD we are emulating.
+
+        # These will be fixed into the database via the database
+        # modifictions below, but we need them set from the start.
         samdb.set_opaque_integer("domainFunctionality", domainFunctionality)
         samdb.set_opaque_integer("forestFunctionality", forestFunctionality)
         samdb.set_opaque_integer("domainControllerFunctionality", domainControllerFunctionality)
@@ -888,9 +909,11 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
             "SCHEMADN": names.schemadn,
             })
 
+        # 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.modify_ldif(schema.schema_dn_modify)
+        samdb.write_prefixes_from_schema()
         samdb.add_ldif(schema.schema_data)
         setup_add_ldif(samdb, setup_path("aggregate_schema.ldif"), 
                        {"SCHEMADN": names.schemadn})
@@ -1204,20 +1227,28 @@ def provision(setup_dir, message, session_info,
         setup_file(setup_path("ldap_backend_startup.sh"), paths.ldapdir + "/ldap_backend_startup.sh", {
                 "SLAPD_COMMAND" : slapd_command})
 
+    
     create_phpldapadmin_config(paths.phpldapadminconfig, setup_path, 
                                ldapi_url)
 
     message("Please install the phpLDAPadmin configuration located at %s into /etc/phpldapadmin/config.php" % paths.phpldapadminconfig)
 
     message("Once the above files are installed, your Samba4 server will be ready to use")
-    message("Server Role:    %s" % serverrole)
-    message("Hostname:       %s" % names.hostname)
-    message("NetBIOS Domain: %s" % names.domain)
-    message("DNS Domain:     %s" % names.dnsdomain)
-    message("DOMAIN SID:     %s" % str(domainsid))
+    message("Server Role:           %s" % serverrole)
+    message("Hostname:              %s" % names.hostname)
+    message("NetBIOS Domain:        %s" % names.domain)
+    message("DNS Domain:            %s" % names.dnsdomain)
+    message("DOMAIN SID:            %s" % str(domainsid))
     if samdb_fill == FILL_FULL:
-        message("Admin password: %s" % adminpass)
+        message("Admin password:    %s" % adminpass)
+    if provision_backend:
+        if provision_backend.credentials.get_bind_dn() is not None:
+            message("LDAP Backend Admin DN: %s" % provision_backend.credentials.get_bind_dn())
+        else:
+            message("LDAP Admin User:       %s" % provision_backend.credentials.get_username())
 
+        message("LDAP Admin Password:   %s" % provision_backend.credentials.get_password())
+  
     result = ProvisionResult()
     result.domaindn = domaindn
     result.paths = paths
@@ -1306,7 +1337,7 @@ class ProvisionBackend(object):
             except:
                 pass
             
-            raise("Warning: Another slapd Instance seems already running on this host, listening to " + ldapi_uri + ". Please shut it down before you continue. ")
+            raise("Warning: Another slapd Instance seems already running on this host, listening to " + self.ldapi_uri + ". Please shut it down before you continue. ")
         
         except LdbError, e:
             pass
@@ -1340,6 +1371,8 @@ class ProvisionBackend(object):
 
         self.credentials = Credentials()
         self.credentials.guess(lp)
+        #Kerberos to an ldapi:// backend makes no sense
+        self.credentials.set_kerberos_state(DONT_USE_KERBEROS)
         self.ldap_backend_type = ldap_backend_type
 
         if ldap_backend_type == "fedora-ds":