2007-12-10 09:29:00 +01:00
#
# backend code for provisioning a Samba4 server
# Released under the GNU GPL v2 or later
2007-12-19 23:27:24 +01:00
# Copyright Jelmer Vernooij 2007
#
# Based on the original in EJS:
# Copyright Andrew Tridgell 2005
2007-12-10 09:29:00 +01:00
#
from base64 import b64encode
import os
import pwd
import grp
import time
2007-12-17 04:56:54 +01:00
import uuid , misc
2007-12-10 09:29:00 +01:00
from socket import gethostname , gethostbyname
import param
import registry
2007-12-17 20:03:06 +01:00
import samba
2007-12-10 10:29:45 +01:00
from samba import Ldb , substitute_var , valid_netbios_name
2007-12-17 08:20:20 +01:00
from samba . samdb import SamDB
2007-12-17 11:12:36 +01:00
import security
2007-12-10 09:29:00 +01:00
from ldb import Dn , SCOPE_SUBTREE , SCOPE_ONELEVEL , SCOPE_BASE , LdbError , \
2007-12-19 23:27:38 +01:00
LDB_ERR_NO_SUCH_OBJECT , timestring , CHANGETYPE_MODIFY , CHANGETYPE_NONE
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:24 +01:00
DEFAULTSITE = " Default-First-Site-Name "
2007-12-10 09:29:00 +01:00
class InvalidNetbiosName ( Exception ) :
def __init__ ( self , name ) :
super ( InvalidNetbiosName , self ) . __init__ ( " The name ' %r ' is not a valid NetBIOS name " % name )
class ProvisionPaths :
def __init__ ( self ) :
self . smbconf = None
self . shareconf = None
self . hklm = None
self . hkcu = None
self . hkcr = None
self . hku = None
self . hkpd = None
self . hkpt = None
self . samdb = None
self . secrets = None
self . keytab = None
2007-12-18 17:21:20 +01:00
self . dns_keytab = None
2007-12-10 09:29:00 +01:00
self . dns = None
self . winsdb = None
self . ldap_basedn_ldif = None
self . ldap_config_basedn_ldif = None
self . ldap_schema_basedn_ldif = None
def install_ok ( lp , session_info , credentials ) :
""" Check whether the current install seems ok. """
2007-12-17 23:16:12 +01:00
if lp . get ( " realm " ) == " " :
2007-12-10 09:29:00 +01:00
return False
2007-12-17 23:16:12 +01:00
ldb = Ldb ( lp . get ( " sam database " ) , session_info = session_info ,
credentials = credentials , lp = lp )
2007-12-19 23:27:38 +01:00
if len ( ldb . search ( ldb . Dn ( " (cn=Administrator) " ) ) ) != 1 :
2007-12-10 09:29:00 +01:00
return False
return True
def findnss ( nssfn , * names ) :
""" Find a user or group from a list of possibilities. """
for name in names :
try :
return nssfn ( name )
except KeyError :
pass
raise Exception ( " Unable to find user/group for %s " % arguments [ 1 ] )
2007-12-17 23:16:12 +01:00
def open_ldb ( session_info , credentials , lp , dbname ) :
2007-12-10 09:29:00 +01:00
assert session_info is not None
try :
2007-12-17 23:16:12 +01:00
return Ldb ( dbname , session_info = session_info , credentials = credentials ,
lp = lp )
2007-12-10 09:29:00 +01:00
except LdbError , e :
print e
os . unlink ( dbname )
2007-12-17 23:16:12 +01:00
return Ldb ( dbname , session_info = session_info , credentials = credentials ,
lp = lp )
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:38 +01:00
def setup_add_ldif ( ldb , ldif_path , subst_vars = None ) :
2007-12-10 09:29:00 +01:00
""" Setup a ldb in the private dir. """
2007-12-19 23:27:38 +01:00
assert isinstance ( ldif_path , str )
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:38 +01:00
data = open ( ldif_path , ' r ' ) . read ( )
2007-12-18 17:21:13 +01:00
if subst_vars is not None :
data = substitute_var ( data , subst_vars )
2007-12-10 09:29:00 +01:00
2007-12-18 17:21:20 +01:00
assert " $ { " not in data
2007-12-19 23:27:38 +01:00
ldb . load_ldif_add ( data )
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:38 +01:00
def setup_modify_ldif ( ldb , ldif_path , substvars = None ) :
2007-12-18 18:54:19 +01:00
""" Modify a ldb in the private dir.
: param ldb : LDB object .
2007-12-19 23:27:38 +01:00
: param ldif_path : LDIF file path .
2007-12-18 18:54:19 +01:00
: param substvars : Optional dictionary with substitution variables .
"""
2007-12-19 23:27:38 +01:00
data = open ( ldif_path , ' r ' ) . read ( )
2007-12-18 17:21:13 +01:00
if substvars is not None :
data = substitute_var ( data , substvars )
2007-12-10 09:29:00 +01:00
2007-12-18 17:21:20 +01:00
assert " $ { " not in data
2007-12-10 09:29:00 +01:00
for ( changetype , msg ) in ldb . parse_ldif ( data ) :
2007-12-19 23:27:38 +01:00
assert changetype == CHANGETYPE_MODIFY
2007-12-10 09:29:00 +01:00
ldb . modify ( msg )
2007-12-19 23:27:38 +01:00
def setup_ldb ( ldb , ldif_path , subst_vars ) :
2007-12-10 09:29:00 +01:00
assert ldb is not None
ldb . transaction_start ( )
try :
2007-12-19 23:27:38 +01:00
setup_add_ldif ( ldb , ldif_path , subst_vars )
2007-12-10 09:29:00 +01:00
except :
ldb . transaction_cancel ( )
raise
ldb . transaction_commit ( )
2007-12-19 23:27:38 +01:00
def setup_file ( template , fname , substvars ) :
2007-12-10 09:29:00 +01:00
""" Setup a file in the private dir. """
f = fname
2007-12-18 17:21:13 +01:00
if os . path . exists ( f ) :
os . unlink ( f )
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:38 +01:00
data = open ( template , ' r ' ) . read ( )
2007-12-18 17:21:20 +01:00
if substvars :
data = substitute_var ( data , substvars )
2007-12-10 09:29:00 +01:00
assert not " $ { " in data
open ( f , ' w ' ) . write ( data )
2007-12-19 23:27:24 +01:00
def provision_default_paths ( lp , dnsdomain ) :
2007-12-10 09:29:00 +01:00
""" Set the default paths for provisioning.
: param lp : Loadparm context .
2007-12-19 23:27:24 +01:00
: param dnsdomain : DNS Domain name
2007-12-10 09:29:00 +01:00
"""
paths = ProvisionPaths ( )
2007-12-17 23:16:12 +01:00
private_dir = lp . get ( " private dir " )
2007-12-10 09:29:00 +01:00
paths . shareconf = os . path . join ( private_dir , " share.ldb " )
2007-12-18 02:21:28 +01:00
paths . samdb = os . path . join ( private_dir , lp . get ( " sam database " ) or " samdb.ldb " )
paths . secrets = os . path . join ( private_dir , lp . get ( " secrets database " ) or " secrets.ldb " )
2007-12-10 09:29:00 +01:00
paths . templates = os . path . join ( private_dir , " templates.ldb " )
paths . keytab = os . path . join ( private_dir , " secrets.keytab " )
2007-12-18 17:21:20 +01:00
paths . dns_keytab = os . path . join ( private_dir , " dns.keytab " )
2007-12-19 23:27:24 +01:00
paths . dns = os . path . join ( private_dir , dnsdomain + " .zone " )
2007-12-10 09:29:00 +01:00
paths . winsdb = os . path . join ( private_dir , " wins.ldb " )
2007-12-17 23:16:16 +01:00
paths . ldap_basedn_ldif = os . path . join ( private_dir ,
2007-12-19 23:27:24 +01:00
dnsdomain + " .ldif " )
2007-12-17 23:16:16 +01:00
paths . ldap_config_basedn_ldif = os . path . join ( private_dir ,
2007-12-19 23:27:24 +01:00
dnsdomain + " -config.ldif " )
2007-12-17 23:16:16 +01:00
paths . ldap_schema_basedn_ldif = os . path . join ( private_dir ,
2007-12-19 23:27:24 +01:00
dnsdomain + " -schema.ldif " )
2007-12-10 09:29:00 +01:00
paths . s4_ldapi_path = os . path . join ( private_dir , " ldapi " )
2007-12-17 23:16:16 +01:00
paths . phpldapadminconfig = os . path . join ( private_dir ,
" phpldapadmin-config.php " )
2007-12-10 09:29:00 +01:00
paths . hklm = os . path . join ( private_dir , " hklm.ldb " )
2007-12-18 17:21:20 +01:00
paths . sysvol = lp . get ( " sysvol " , " path " )
if paths . sysvol is None :
paths . sysvol = os . path . join ( lp . get ( " lock dir " ) , " sysvol " )
paths . netlogon = lp . get ( " netlogon " , " path " )
if paths . netlogon is None :
paths . netlogon = os . path . join ( os . path . join ( paths . sysvol , " scripts " ) )
2007-12-10 09:29:00 +01:00
return paths
2007-12-19 23:27:24 +01:00
def setup_name_mappings ( ldb , sid , domaindn , root , nobody , nogroup , users ,
wheel , backup ) :
2007-12-10 09:29:00 +01:00
""" setup reasonable name mappings for sam names to unix names. """
# add some foreign sids if they are not present already
2007-12-19 23:27:24 +01:00
ldb . add_foreign ( domaindn , " S-1-5-7 " , " Anonymous " )
ldb . add_foreign ( domaindn , " S-1-1-0 " , " World " )
ldb . add_foreign ( domaindn , " S-1-5-2 " , " Network " )
ldb . add_foreign ( domaindn , " S-1-5-18 " , " System " )
ldb . add_foreign ( domaindn , " S-1-5-11 " , " Authenticated Users " )
2007-12-10 09:29:00 +01:00
# some well known sids
2007-12-19 23:27:24 +01:00
ldb . setup_name_mapping ( domaindn , " S-1-5-7 " , nobody )
ldb . setup_name_mapping ( domaindn , " S-1-1-0 " , nogroup )
ldb . setup_name_mapping ( domaindn , " S-1-5-2 " , nogroup )
ldb . setup_name_mapping ( domaindn , " S-1-5-18 " , root )
ldb . setup_name_mapping ( domaindn , " S-1-5-11 " , users )
ldb . setup_name_mapping ( domaindn , " S-1-5-32-544 " , wheel )
ldb . setup_name_mapping ( domaindn , " S-1-5-32-545 " , users )
ldb . setup_name_mapping ( domaindn , " S-1-5-32-546 " , nogroup )
ldb . setup_name_mapping ( domaindn , " S-1-5-32-551 " , backup )
2007-12-10 09:29:00 +01:00
# and some well known domain rids
2007-12-19 23:27:24 +01:00
ldb . setup_name_mapping ( domaindn , sid + " -500 " , root )
ldb . setup_name_mapping ( domaindn , sid + " -518 " , wheel )
ldb . setup_name_mapping ( domaindn , sid + " -519 " , wheel )
ldb . setup_name_mapping ( domaindn , sid + " -512 " , wheel )
ldb . setup_name_mapping ( domaindn , sid + " -513 " , users )
ldb . setup_name_mapping ( domaindn , sid + " -520 " , wheel )
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:24 +01:00
def provision_become_dc ( setup_dir , message , paths , lp , session_info ,
2007-12-10 09:29:00 +01:00
credentials ) :
assert session_info is not None
2007-12-19 23:27:38 +01:00
erase = False
def setup_path ( file ) :
return os . path . join ( setup_dir , file )
os . path . unlink ( paths . samdb )
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:38 +01:00
message ( " Setting up templates db " )
2007-12-20 15:53:56 +01:00
setup_templatesdb ( paths . templates , setup_path , session_info = session_info ,
credentials = credentials , lp = lp )
2007-12-10 09:29:00 +01:00
# Also wipes the database
2007-12-19 23:27:38 +01:00
message ( " Setting up sam.ldb " )
2007-12-20 15:53:56 +01:00
samdb = SamDB ( paths . samdb , session_info = session_info ,
credentials = credentials , lp = lp )
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:38 +01:00
message ( " Setting up sam.ldb partitions " )
2007-12-20 15:53:56 +01:00
setup_samdb_partitions ( samdb , setup_path , schemadn , configdn , domaindn )
2007-12-18 17:21:13 +01:00
2007-12-20 15:53:56 +01:00
samdb = SamDB ( paths . samdb , session_info = session_info ,
credentials = credentials , lp = lp )
2007-12-18 17:21:13 +01:00
2007-12-10 09:29:00 +01:00
ldb . transaction_start ( )
try :
2007-12-19 23:27:38 +01:00
message ( " Setting up sam.ldb attributes " )
samdb . load_ldif_file_add ( setup_path ( " provision_init.ldif " ) )
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:38 +01:00
message ( " Setting up sam.ldb rootDSE " )
setup_samdb_rootdse ( samdb , setup_path , schemadn , domaindn ,
2007-12-19 23:27:24 +01:00
hostname , dnsdomain , realm , rootdn , configdn ,
netbiosname )
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:38 +01:00
if erase :
message ( " Erasing data from partitions " )
samdb . erase_partitions ( )
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:38 +01:00
message ( " Setting up sam.ldb indexes " )
samdb . load_ldif_file_add ( setup_path ( " provision_index.ldif " ) )
2007-12-10 09:29:00 +01:00
except :
samdb . transaction_cancel ( )
raise
samdb . transaction_commit ( )
message ( " Setting up %s " % paths . secrets )
2007-12-20 15:53:56 +01:00
secrets_ldb = setup_secretsdb ( paths . secrets , setup_path , session_info ,
credentials , lp )
2007-12-19 23:27:38 +01:00
setup_ldb ( secrets_ldb , setup_path ( " secrets_dc.ldif " ) ,
2007-12-19 23:27:24 +01:00
{ " MACHINEPASS_B64 " : b64encode ( machinepass ) } )
2007-12-18 17:21:13 +01:00
2007-12-19 23:27:38 +01:00
def setup_secretsdb ( path , setup_path , session_info , credentials , lp ) :
2007-12-20 15:53:56 +01:00
if os . path . exists ( path ) :
os . unlink ( path )
2007-12-18 17:21:13 +01:00
secrets_ldb = Ldb ( path , session_info = session_info , credentials = credentials , lp = lp )
secrets_ldb . erase ( )
2007-12-19 23:27:38 +01:00
secrets_ldb . load_ldif_file_add ( setup_path ( " secrets_init.ldif " ) )
secrets_ldb . load_ldif_file_add ( setup_path ( " secrets.ldif " ) )
2007-12-18 17:21:13 +01:00
return secrets_ldb
2007-12-19 23:27:38 +01:00
def setup_templatesdb ( path , setup_path , session_info , credentials , lp ) :
templates_ldb = SamDB ( path , session_info = session_info ,
2007-12-18 17:21:13 +01:00
credentials = credentials , lp = lp )
templates_ldb . erase ( )
2007-12-19 23:27:38 +01:00
templates_ldb . load_ldif_file_add ( setup_path ( " provision_templates.ldif " ) )
2007-12-18 17:21:13 +01:00
2007-12-19 23:27:38 +01:00
def setup_registry ( path , setup_path , session_info , credentials , lp ) :
2007-12-18 17:21:13 +01:00
reg = registry . Registry ( )
hive = registry . Hive ( path , session_info = session_info ,
credentials = credentials , lp_ctx = lp )
reg . mount_hive ( hive , " HKEY_LOCAL_MACHINE " )
2007-12-19 23:27:38 +01:00
provision_reg = setup_path ( " provision.reg " )
2007-12-18 17:21:13 +01:00
assert os . path . exists ( provision_reg )
reg . apply_patchfile ( provision_reg )
2007-12-19 23:27:38 +01:00
def setup_samdb_rootdse ( samdb , setup_path , schemadn , domaindn , hostname ,
2007-12-19 23:27:24 +01:00
dnsdomain , realm , rootdn , configdn , netbiosname ) :
2007-12-19 23:27:38 +01:00
setup_add_ldif ( samdb , setup_path ( " provision_rootdse_add.ldif " ) , {
2007-12-19 23:27:24 +01:00
" SCHEMADN " : schemadn ,
" NETBIOSNAME " : netbiosname ,
" DNSDOMAIN " : dnsdomain ,
" DEFAULTSITE " : DEFAULTSITE ,
" REALM " : realm ,
" DNSNAME " : " %s . %s " % ( hostname , dnsdomain ) ,
" DOMAINDN " : domaindn ,
" ROOTDN " : rootdn ,
" CONFIGDN " : configdn ,
2007-12-18 17:21:13 +01:00
" VERSION " : samba . version ( ) ,
} )
2007-12-19 23:27:38 +01:00
def setup_samdb_partitions ( samdb , setup_path , schemadn , configdn , domaindn ) :
2007-12-18 17:21:24 +01:00
#Add modules to the list to activate them by default
#beware often order is important
#
# Some Known ordering constraints:
# - rootdse must be first, as it makes redirects from "" -> cn=rootdse
# - objectclass must be before password_hash, because password_hash checks
# that the objectclass is of type person (filled in by objectclass
# module when expanding the objectclass list)
# - partition must be last
# - each partition has its own module list then
modules_list = [ " rootdse " ,
" paged_results " ,
" ranged_results " ,
" anr " ,
" server_sort " ,
" extended_dn " ,
" asq " ,
" samldb " ,
" rdn_name " ,
" objectclass " ,
" kludge_acl " ,
" operational " ]
tdb_modules_list = [
" subtree_rename " ,
" subtree_delete " ,
" linked_attributes " ]
modules_list2 = [ " show_deleted " ,
" partition " ]
2007-12-19 23:27:38 +01:00
setup_add_ldif ( samdb , setup_path ( " provision_partitions.ldif " ) , {
2007-12-18 17:21:24 +01:00
" SCHEMADN " : schemadn ,
2007-12-18 17:21:13 +01:00
" SCHEMADN_LDB " : " schema.ldb " ,
" SCHEMADN_MOD2 " : " ,objectguid " ,
2007-12-18 17:21:24 +01:00
" CONFIGDN " : configdn ,
2007-12-18 17:21:13 +01:00
" CONFIGDN_LDB " : " configuration.ldb " ,
2007-12-18 17:21:24 +01:00
" DOMAINDN " : domaindn ,
2007-12-18 17:21:13 +01:00
" DOMAINDN_LDB " : " users.ldb " ,
" SCHEMADN_MOD " : " schema_fsmo " ,
" CONFIGDN_MOD " : " naming_fsmo " ,
" CONFIGDN_MOD2 " : " ,objectguid " ,
" DOMAINDN_MOD " : " pdc_fsmo,password_hash " ,
" DOMAINDN_MOD2 " : " ,objectguid " ,
2007-12-18 17:21:24 +01:00
" MODULES_LIST " : " , " . join ( modules_list ) ,
" TDB_MODULES_LIST " : " , " + " , " . join ( tdb_modules_list ) ,
" MODULES_LIST2 " : " , " . join ( modules_list2 ) ,
2007-12-18 17:21:13 +01:00
} )
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:24 +01:00
def provision ( lp , setup_dir , message , blank , paths , session_info ,
credentials , ldapbackend , realm = None , domain = None , hostname = None ,
hostip = None , domainsid = None , hostguid = None , adminpass = None ,
krbtgtpass = None , domainguid = None , policyguid = None ,
invocationid = None , machinepass = None , dnspass = None , root = None ,
nobody = None , nogroup = None , users = None , wheel = None , backup = None ,
aci = None , serverrole = None ) :
2007-12-10 09:29:00 +01:00
""" Provision samba4
: note : caution , this wipes all existing data !
"""
2007-12-19 23:27:24 +01:00
2007-12-19 23:27:38 +01:00
def setup_path ( file ) :
return os . path . join ( setup_dir , file )
erase = False
2007-12-19 23:27:24 +01:00
if domainsid is None :
domainsid = security . random_sid ( )
if policyguid is None :
policyguid = uuid . random ( )
if invocationid is None :
invocationid = uuid . random ( )
if adminpass is None :
adminpass = misc . random_password ( 12 )
if krbtgtpass is None :
krbtgtpass = misc . random_password ( 12 )
if machinepass is None :
machinepass = misc . random_password ( 12 )
if dnspass is None :
dnspass = misc . random_password ( 12 )
if root is None :
root = findnss ( pwd . getpwnam , " root " ) [ 4 ]
if nobody is None :
nobody = findnss ( pwd . getpwnam , " nobody " ) [ 4 ]
if nogroup is None :
nogroup = findnss ( grp . getgrnam , " nogroup " , " nobody " ) [ 2 ]
if users is None :
users = findnss ( grp . getgrnam , " users " , " guest " , " other " , " unknown " , " usr " ) [ 2 ]
if wheel is None :
wheel = findnss ( grp . getgrnam , " wheel " , " root " , " staff " , " adm " ) [ 2 ]
if backup is None :
backup = findnss ( grp . getgrnam , " backup " , " wheel " , " root " , " staff " ) [ 2 ]
if aci is None :
aci = " # no aci for local ldb "
if serverrole is None :
serverrole = lp . get ( " server role " )
if realm is None :
realm = lp . get ( " realm " )
else :
if lp . get ( " realm " ) . upper ( ) != realm . upper ( ) :
raise Error ( " realm ' %s ' in smb.conf must match chosen realm ' %s ' \n " %
( lp . get ( " realm " ) , realm ) )
assert realm is not None
realm = realm . upper ( )
if domain is None :
domain = lp . get ( " workgroup " )
else :
if lp . get ( " workgroup " ) . upper ( ) != domain . upper ( ) :
raise Error ( " workgroup ' %s ' in smb.conf must match chosen domain ' %s ' \n " ,
lp . get ( " workgroup " ) , domain )
assert domain is not None
domain = domain . upper ( )
if not valid_netbios_name ( domain ) :
raise InvalidNetbiosName ( domain )
if hostname is None :
hostname = gethostname ( ) . split ( " . " ) [ 0 ] . lower ( )
if hostip is None :
hostip = gethostbyname ( hostname )
netbiosname = hostname . upper ( )
if not valid_netbios_name ( netbiosname ) :
raise InvalidNetbiosName ( netbiosname )
dnsdomain = realm . lower ( )
domaindn = " DC= " + dnsdomain . replace ( " . " , " ,DC= " )
rootdn = domaindn
configdn = " CN=Configuration, " + rootdn
schemadn = " CN=Schema, " + configdn
rdn_dc = domaindn . split ( " , " ) [ 0 ] [ len ( " DC= " ) : ]
2007-12-19 23:27:38 +01:00
message ( " set DOMAIN SID: %s " % str ( domainsid ) )
2007-12-19 23:27:24 +01:00
message ( " Provisioning for %s in realm %s " % ( domain , realm ) )
message ( " Using administrator password: %s " % adminpass )
2007-12-10 09:29:00 +01:00
assert paths . smbconf is not None
# only install a new smb.conf if there isn't one there already
if not os . path . exists ( paths . smbconf ) :
message ( " Setting up smb.conf " )
2007-12-19 23:27:24 +01:00
if serverrole == " domain controller " :
2007-12-18 17:21:13 +01:00
smbconfsuffix = " dc "
2007-12-19 23:27:24 +01:00
elif serverrole == " member " :
2007-12-18 17:21:13 +01:00
smbconfsuffix = " member "
else :
2007-12-19 23:27:24 +01:00
assert " Invalid server role setting: %s " % serverrole
2007-12-19 23:27:38 +01:00
setup_file ( setup_path ( " provision.smb.conf. %s " % smbconfsuffix ) , paths . smbconf , {
" HOSTNAME " : hostname ,
" DOMAIN_CONF " : domain ,
" REALM_CONF " : realm ,
" SERVERROLE " : serverrole ,
" NETLOGONPATH " : paths . netlogon ,
" SYSVOLPATH " : paths . sysvol ,
} )
2007-12-10 09:29:00 +01:00
lp . reload ( )
# only install a new shares config db if there is none
if not os . path . exists ( paths . shareconf ) :
message ( " Setting up share.ldb " )
2007-12-18 02:21:28 +01:00
share_ldb = Ldb ( paths . shareconf , session_info = session_info ,
credentials = credentials , lp = lp )
2007-12-19 23:27:38 +01:00
share_ldb . load_ldif_file_add ( setup_path ( " share.ldif " ) )
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:38 +01:00
message ( " Setting up secrets.ldb " )
2007-12-20 15:53:56 +01:00
secrets_ldb = setup_secretsdb ( paths . secrets , setup_path ,
session_info = session_info ,
credentials = credentials , lp = lp )
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:38 +01:00
message ( " Setting up the registry " )
2007-12-18 17:21:20 +01:00
# FIXME: Still fails for some reason
2007-12-19 23:27:38 +01:00
#setup_registry(paths.hklm, setup_path, session_info,
2007-12-18 17:21:13 +01:00
# credentials=credentials, lp=lp)
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:38 +01:00
message ( " Setting up templates db " )
setup_templatesdb ( paths . templates , setup_path , session_info = session_info ,
2007-12-18 17:21:13 +01:00
credentials = credentials , lp = lp )
2007-12-10 09:29:00 +01:00
2007-12-20 15:53:56 +01:00
# Also wipes the database
message ( " Setting up sam.ldb " )
2007-12-18 02:21:28 +01:00
samdb = SamDB ( paths . samdb , session_info = session_info ,
credentials = credentials , lp = lp )
2007-12-18 17:21:13 +01:00
message ( " Setting up sam.ldb partitions " )
2007-12-19 23:27:38 +01:00
setup_samdb_partitions ( samdb , setup_path , schemadn , configdn , domaindn )
2007-12-10 09:29:00 +01:00
2007-12-18 02:21:14 +01:00
samdb = SamDB ( paths . samdb , session_info = session_info ,
credentials = credentials , lp = lp )
2007-12-18 17:21:13 +01:00
2007-12-10 09:29:00 +01:00
samdb . transaction_start ( )
try :
message ( " Setting up sam.ldb attributes " )
2007-12-19 23:27:38 +01:00
samdb . load_ldif_file_add ( setup_path ( " provision_init.ldif " ) )
2007-12-10 09:29:00 +01:00
message ( " Setting up sam.ldb rootDSE " )
2007-12-19 23:27:38 +01:00
setup_samdb_rootdse ( samdb , setup_path , schemadn , domaindn ,
2007-12-19 23:27:24 +01:00
hostname , dnsdomain , realm , rootdn , configdn ,
netbiosname )
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:38 +01:00
if erase :
message ( " Erasing data from partitions " )
samdb . erase_partitions ( )
2007-12-10 09:29:00 +01:00
except :
samdb . transaction_cancel ( )
raise
samdb . transaction_commit ( )
message ( " Pre-loading the Samba 4 and AD schema " )
2007-12-17 23:16:12 +01:00
samdb = SamDB ( paths . samdb , session_info = session_info ,
credentials = credentials , lp = lp )
2007-12-19 23:27:24 +01:00
samdb . set_domain_sid ( domainsid )
2007-12-19 23:27:38 +01:00
load_schema ( setup_path , samdb , schemadn , netbiosname , configdn )
2007-12-10 09:29:00 +01:00
samdb . transaction_start ( )
try :
2007-12-19 23:27:24 +01:00
message ( " Adding DomainDN: %s (permitted to fail) " % domaindn )
2007-12-19 23:27:38 +01:00
setup_add_ldif ( samdb , setup_path ( " provision_basedn.ldif " ) , {
2007-12-19 23:27:24 +01:00
" DOMAINDN " : domaindn ,
" ACI " : aci ,
2007-12-18 17:21:13 +01:00
" EXTENSIBLEOBJECT " : " # no objectClass: extensibleObject for local ldb " ,
2007-12-19 23:27:24 +01:00
" RDN_DC " : rdn_dc ,
2007-12-18 17:21:13 +01:00
} )
2007-12-19 23:27:24 +01:00
message ( " Modifying DomainDN: " + domaindn + " " )
if domainguid is not None :
domainguid_mod = " replace: objectGUID \n objectGUID: %s \n - " % domainguid
2007-12-18 17:21:13 +01:00
else :
domainguid_mod = " "
2007-12-19 23:27:38 +01:00
setup_modify_ldif ( samdb , setup_path ( " provision_basedn_modify.ldif " ) , {
2007-12-19 23:27:24 +01:00
" RDN_DC " : rdn_dc ,
2007-12-18 17:21:13 +01:00
" LDAPTIME " : timestring ( int ( time . time ( ) ) ) ,
2007-12-19 23:27:24 +01:00
" DOMAINSID " : str ( domainsid ) ,
" SCHEMADN " : schemadn ,
" NETBIOSNAME " : netbiosname ,
" DEFAULTSITE " : DEFAULTSITE ,
" CONFIGDN " : configdn ,
" POLICYGUID " : policyguid ,
" DOMAINDN " : domaindn ,
2007-12-18 17:21:13 +01:00
" DOMAINGUID_MOD " : domainguid_mod ,
2007-12-18 17:21:24 +01:00
} )
2007-12-10 09:29:00 +01:00
message ( " Adding configuration container (permitted to fail) " )
2007-12-19 23:27:38 +01:00
setup_add_ldif ( samdb , setup_path ( " provision_configuration_basedn.ldif " ) , {
2007-12-19 23:27:24 +01:00
" CONFIGDN " : configdn ,
" ACI " : aci ,
2007-12-18 17:21:13 +01:00
" EXTENSIBLEOBJECT " : " # no objectClass: extensibleObject for local ldb " ,
} )
2007-12-10 09:29:00 +01:00
message ( " Modifying configuration container " )
2007-12-19 23:27:38 +01:00
setup_modify_ldif ( samdb , setup_path ( " provision_configuration_basedn_modify.ldif " ) , {
2007-12-19 23:27:24 +01:00
" CONFIGDN " : configdn ,
" SCHEMADN " : schemadn ,
2007-12-18 17:21:24 +01:00
} )
2007-12-10 09:29:00 +01:00
message ( " Adding schema container (permitted to fail) " )
2007-12-19 23:27:38 +01:00
setup_add_ldif ( samdb , setup_path ( " provision_schema_basedn.ldif " ) , {
2007-12-19 23:27:24 +01:00
" SCHEMADN " : schemadn ,
" ACI " : aci ,
2007-12-18 17:21:13 +01:00
" EXTENSIBLEOBJECT " : " # no objectClass: extensibleObject for local ldb "
} )
2007-12-10 09:29:00 +01:00
message ( " Modifying schema container " )
2007-12-19 23:27:38 +01:00
setup_modify_ldif ( samdb , setup_path ( " provision_schema_basedn_modify.ldif " ) , {
2007-12-19 23:27:24 +01:00
" SCHEMADN " : schemadn ,
" NETBIOSNAME " : netbiosname ,
" DEFAULTSITE " : DEFAULTSITE ,
" CONFIGDN " : configdn ,
2007-12-18 17:21:24 +01:00
} )
2007-12-18 17:21:13 +01:00
2007-12-10 09:29:00 +01:00
message ( " Setting up sam.ldb Samba4 schema " )
2007-12-19 23:27:38 +01:00
setup_add_ldif ( samdb , setup_path ( " schema_samba4.ldif " ) ,
2007-12-19 23:27:24 +01:00
{ " SCHEMADN " : schemadn } )
2007-12-10 09:29:00 +01:00
message ( " Setting up sam.ldb AD schema " )
2007-12-19 23:27:38 +01:00
setup_add_ldif ( samdb , setup_path ( " schema.ldif " ) ,
2007-12-19 23:27:24 +01:00
{ " SCHEMADN " : schemadn } )
2007-12-10 09:29:00 +01:00
message ( " Setting up sam.ldb configuration data " )
2007-12-19 23:27:38 +01:00
setup_add_ldif ( samdb , setup_path ( " provision_configuration.ldif " ) , {
2007-12-19 23:27:24 +01:00
" CONFIGDN " : configdn ,
" NETBIOSNAME " : netbiosname ,
" DEFAULTSITE " : DEFAULTSITE ,
" DNSDOMAIN " : dnsdomain ,
" DOMAIN " : domain ,
" SCHEMADN " : schemadn ,
" DOMAINDN " : domaindn ,
2007-12-18 17:21:13 +01:00
} )
2007-12-10 09:29:00 +01:00
message ( " Setting up display specifiers " )
2007-12-19 23:27:38 +01:00
setup_add_ldif ( samdb , setup_path ( " display_specifiers.ldif " ) ,
{ " CONFIGDN " : configdn } )
2007-12-10 09:29:00 +01:00
message ( " Adding users container (permitted to fail) " )
2007-12-19 23:27:38 +01:00
setup_add_ldif ( samdb , setup_path ( " provision_users_add.ldif " ) , {
2007-12-19 23:27:24 +01:00
" DOMAINDN " : domaindn } )
2007-12-10 09:29:00 +01:00
message ( " Modifying users container " )
2007-12-19 23:27:38 +01:00
setup_modify_ldif ( samdb , setup_path ( " provision_users_modify.ldif " ) , {
2007-12-19 23:27:24 +01:00
" DOMAINDN " : domaindn } )
2007-12-10 09:29:00 +01:00
message ( " Adding computers container (permitted to fail) " )
2007-12-19 23:27:38 +01:00
setup_add_ldif ( samdb , setup_path ( " provision_computers_add.ldif " ) , {
2007-12-19 23:27:24 +01:00
" DOMAINDN " : domaindn } )
2007-12-10 09:29:00 +01:00
message ( " Modifying computers container " )
2007-12-19 23:27:38 +01:00
setup_modify_ldif ( samdb , setup_path ( " provision_computers_modify.ldif " ) , {
2007-12-19 23:27:24 +01:00
" DOMAINDN " : domaindn } )
2007-12-10 09:29:00 +01:00
message ( " Setting up sam.ldb data " )
2007-12-19 23:27:38 +01:00
setup_add_ldif ( samdb , setup_path ( " provision.ldif " ) , {
2007-12-19 23:27:24 +01:00
" DOMAINDN " : domaindn ,
" NETBIOSNAME " : netbiosname ,
" DEFAULTSITE " : DEFAULTSITE ,
" CONFIGDN " : configdn ,
2007-12-18 17:21:13 +01:00
} )
2007-12-10 09:29:00 +01:00
2007-12-18 17:21:20 +01:00
if not blank :
message ( " Setting up sam.ldb users and groups " )
2007-12-19 23:27:38 +01:00
setup_add_ldif ( samdb , setup_path ( " provision_users.ldif " ) , {
2007-12-19 23:27:24 +01:00
" DOMAINDN " : domaindn ,
" DOMAINSID " : str ( domainsid ) ,
" CONFIGDN " : configdn ,
" ADMINPASS_B64 " : b64encode ( adminpass ) ,
" KRBTGTPASS_B64 " : b64encode ( krbtgtpass ) ,
2007-12-18 17:21:20 +01:00
} )
if lp . get ( " server role " ) == " domain controller " :
message ( " Setting up self join " )
2007-12-19 23:27:24 +01:00
if hostguid is not None :
hostguid_add = " objectGUID: %s " % hostguid
2007-12-18 17:21:20 +01:00
else :
hostguid_add = " "
2007-12-19 23:27:38 +01:00
setup_add_ldif ( samdb , setup_path ( " provision_self_join.ldif " ) , {
2007-12-19 23:27:24 +01:00
" CONFIGDN " : configdn ,
" SCHEMADN " : schemadn ,
" DOMAINDN " : domaindn ,
" INVOCATIONID " : invocationid ,
" NETBIOSNAME " : netbiosname ,
" DEFAULTSITE " : DEFAULTSITE ,
" DNSNAME " : " %s . %s " % ( hostname , dnsdomain ) ,
" MACHINEPASS_B64 " : b64encode ( machinepass ) ,
" DNSPASS_B64 " : b64encode ( dnspass ) ,
" REALM " : realm ,
" DOMAIN " : domain ,
2007-12-18 17:21:20 +01:00
" HOSTGUID_ADD " : hostguid_add ,
2007-12-19 23:27:24 +01:00
" DNSDOMAIN " : dnsdomain } )
2007-12-19 23:27:38 +01:00
setup_add_ldif ( samdb , setup_path ( " provision_group_policy.ldif " ) , {
2007-12-19 23:27:24 +01:00
" POLICYGUID " : policyguid ,
" DNSDOMAIN " : dnsdomain ,
" DOMAINSID " : str ( domainsid ) ,
" DOMAINDN " : domaindn } )
os . makedirs ( os . path . join ( paths . sysvol , dnsdomain , " Policies " , " { " + policyguid + " } " ) , 0755 )
os . makedirs ( os . path . join ( paths . sysvol , dnsdomain , " Policies " , " { " + policyguid + " } " , " Machine " ) , 0755 )
os . makedirs ( os . path . join ( paths . sysvol , dnsdomain , " Policies " , " { " + policyguid + " } " , " User " ) , 0755 )
2007-12-18 17:21:20 +01:00
if not os . path . isdir ( paths . netlogon ) :
os . makedirs ( paths . netlogon , 0755 )
2007-12-19 23:27:38 +01:00
setup_ldb ( secrets_ldb , setup_path ( " secrets_dc.ldif " ) , {
2007-12-19 23:27:24 +01:00
" MACHINEPASS_B64 " : b64encode ( machinepass ) ,
" DOMAIN " : domain ,
" REALM " : realm ,
2007-12-18 17:21:20 +01:00
" LDAPTIME " : timestring ( int ( time . time ( ) ) ) ,
2007-12-19 23:27:24 +01:00
" DNSDOMAIN " : dnsdomain ,
" DOMAINSID " : str ( domainsid ) ,
2007-12-18 17:21:20 +01:00
" SECRETS_KEYTAB " : paths . keytab ,
2007-12-19 23:27:24 +01:00
" NETBIOSNAME " : netbiosname ,
2007-12-18 17:21:20 +01:00
" SAM_LDB " : paths . samdb ,
" DNS_KEYTAB " : paths . dns_keytab ,
2007-12-19 23:27:24 +01:00
" DNSPASS_B64 " : b64encode ( dnspass ) ,
2007-12-18 17:21:20 +01:00
} )
2007-12-19 23:27:24 +01:00
setup_name_mappings ( samdb , str ( domainsid ) ,
domaindn , root = root , nobody = nobody ,
nogroup = nogroup , wheel = wheel , users = users ,
backup = backup )
2007-12-10 09:29:00 +01:00
message ( " Setting up sam.ldb index " )
2007-12-19 23:27:38 +01:00
samdb . load_ldif_file_add ( setup_path ( " provision_index.ldif " ) )
2007-12-10 09:29:00 +01:00
2007-12-20 15:53:56 +01:00
message ( " Setting up sam.ldb rootDSE marking as synchronized " )
2007-12-19 23:27:38 +01:00
setup_modify_ldif ( samdb , setup_path ( " provision_rootdse_modify.ldif " ) )
2007-12-10 09:29:00 +01:00
except :
samdb . transaction_cancel ( )
raise
samdb . transaction_commit ( )
message ( " Setting up phpLDAPadmin configuration " )
2007-12-19 23:27:38 +01:00
create_phplpapdadmin_config ( paths . phpldapadminconfig , setup_path , paths . s4_ldapi_path )
2007-12-18 17:21:13 +01:00
2007-12-10 09:29:00 +01:00
message ( " Please install the phpLDAPadmin configuration located at %s into /etc/phpldapadmin/config.php " % paths . phpldapadminconfig )
2007-12-20 15:53:56 +01:00
samdb = SamDB ( paths . samdb , session_info = session_info ,
credentials = credentials , lp = lp )
domainguid = samdb . searchone ( Dn ( samdb , domaindn ) , " objectGUID " )
assert isinstance ( domainguid , str )
hostguid = samdb . searchone ( Dn ( samdb , domaindn ) , " objectGUID " ,
expression = " (&(objectClass=computer)(cn= %s )) " % hostname ,
scope = SCOPE_SUBTREE )
assert isinstance ( hostguid , str )
2007-12-19 23:27:24 +01:00
message ( " Setting up DNS zone: %s " % dnsdomain )
2007-12-19 23:27:38 +01:00
create_zone_file ( paths . dns , setup_path , samdb ,
2007-12-19 23:27:24 +01:00
hostname = hostname , hostip = hostip , dnsdomain = dnsdomain ,
2007-12-20 15:53:56 +01:00
domaindn = domaindn , dnspass = dnspass , realm = realm ,
domainguid = domainguid , hostguid = hostguid )
2007-12-19 23:27:24 +01:00
message ( " Please install the zone located in %s into your DNS server " % paths . dns )
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:38 +01:00
def create_phplpapdadmin_config ( path , setup_path , s4_ldapi_path ) :
setup_file ( setup_path ( " phpldapadmin-config.php " ) ,
2007-12-18 17:21:13 +01:00
path , { " S4_LDAPI_URI " : " ldapi:// %s " % s4_ldapi_path . replace ( " / " , " %2F " ) } )
2007-12-19 23:27:38 +01:00
def create_zone_file ( path , setup_path , samdb , dnsdomain , domaindn ,
2007-12-20 15:53:56 +01:00
hostip , hostname , dnspass , realm , domainguid , hostguid ) :
2007-12-10 09:29:00 +01:00
""" Write out a DNS zone file, from the info in the current database. """
2007-12-19 23:27:24 +01:00
2007-12-19 23:27:38 +01:00
setup_file ( setup_path ( " provision.zone " ) , path , {
2007-12-19 23:27:24 +01:00
" DNSPASS_B64 " : b64encode ( dnspass ) ,
" HOSTNAME " : hostname ,
" DNSDOMAIN " : dnsdomain ,
" REALM " : realm ,
" HOSTIP " : hostip ,
2007-12-18 17:21:13 +01:00
" DOMAINGUID " : domainguid ,
" DATESTRING " : time . strftime ( " % Y % m %d % H " ) ,
2007-12-19 23:27:24 +01:00
" DEFAULTSITE " : DEFAULTSITE ,
2007-12-18 17:21:13 +01:00
" HOSTGUID " : hostguid ,
} )
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:24 +01:00
def provision_ldapbase ( setup_dir , message , paths ) :
2007-12-10 09:29:00 +01:00
""" Write out a DNS zone file, from the info in the current database. """
2007-12-19 23:27:24 +01:00
message ( " Setting up LDAP base entry: %s " % domaindn )
rdns = domaindn . split ( " , " )
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:24 +01:00
rdn_dc = rdns [ 0 ] [ len ( " DC= " ) : ]
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:38 +01:00
def setup_path ( file ) :
return os . path . join ( setup_dir , file )
setup_file ( setup_path ( " provision_basedn.ldif " ) ,
2007-12-19 23:27:24 +01:00
paths . ldap_basedn_ldif )
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:38 +01:00
setup_file ( setup_path ( " provision_configuration_basedn.ldif " ) ,
2007-12-19 23:27:24 +01:00
paths . ldap_config_basedn_ldif )
2007-12-10 09:29:00 +01:00
2007-12-19 23:27:38 +01:00
setup_file ( setup_path ( " provision_schema_basedn.ldif " ) ,
2007-12-18 17:21:13 +01:00
paths . ldap_schema_basedn_ldif , {
2007-12-19 23:27:24 +01:00
" SCHEMADN " : schemadn ,
2007-12-18 17:21:13 +01:00
" ACI " : " # no aci for local ldb " ,
" EXTENSIBLEOBJECT " : " objectClass: extensibleObject " } )
2007-12-10 09:29:00 +01:00
message ( " Please install the LDIF located in " + paths . ldap_basedn_ldif + " , " + paths . ldap_config_basedn_ldif + " and " + paths . ldap_schema_basedn_ldif + " into your LDAP server, and re-run with --ldap-backend=ldap://my.ldap.server " )
2007-12-19 23:27:38 +01:00
def load_schema ( setup_path , samdb , schemadn , netbiosname , configdn ) :
2007-12-10 09:29:00 +01:00
""" Load schema. """
2007-12-19 23:27:38 +01:00
schema_data = open ( setup_path ( " schema.ldif " ) , ' r ' ) . read ( )
schema_data + = open ( setup_path ( " schema_samba4.ldif " ) , ' r ' ) . read ( )
2007-12-19 23:27:24 +01:00
schema_data = substitute_var ( schema_data , { " SCHEMADN " : schemadn } )
2007-12-19 23:27:38 +01:00
head_data = open ( setup_path ( " provision_schema_basedn_modify.ldif " ) , ' r ' ) . read ( )
2007-12-18 17:21:13 +01:00
head_data = substitute_var ( head_data , {
2007-12-19 23:27:24 +01:00
" SCHEMADN " : schemadn ,
" NETBIOSNAME " : netbiosname ,
" CONFIGDN " : configdn ,
" DEFAULTSITE " : DEFAULTSITE } )
2007-12-17 12:07:51 +01:00
samdb . attach_schema_from_ldif ( head_data , schema_data )
2007-12-10 09:29:00 +01:00
2007-12-18 18:54:19 +01:00
def join_domain ( domain , netbios_name , join_type , creds ) :
2007-12-10 09:29:00 +01:00
ctx = NetContext ( creds )
joindom = object ( )
joindom . domain = domain
joindom . join_type = join_type
joindom . netbios_name = netbios_name
if not ctx . JoinDomain ( joindom ) :
raise Exception ( " Domain Join failed: " + joindom . error_string )
def vampire ( domain , session_info , credentials , message ) :
""" Vampire a remote domain.
Session info and credentials are required for for
access to our local database ( might be remote ldap )
"""
ctx = NetContext ( credentials )
2007-12-18 18:54:19 +01:00
machine_creds = Credentials ( )
2007-12-10 09:29:00 +01:00
machine_creds . set_domain ( form . domain )
if not machine_creds . set_machine_account ( ) :
raise Exception ( " Failed to access domain join information! " )
vampire_ctx . machine_creds = machine_creds
vampire_ctx . session_info = session_info
if not ctx . SamSyncLdb ( vampire_ctx ) :
raise Exception ( " Migration of remote domain to Samba failed: %s " % vampire_ctx . error_string )
2007-12-17 08:20:20 +01:00