2010-11-28 16:09:30 +03:00
# backend code for upgrading from Samba3
# Copyright Jelmer Vernooij 2005-2007
2007-12-10 11:29:00 +03:00
#
2010-11-28 16:09:30 +03:00
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2007-12-10 11:29:00 +03:00
#
""" Support code for upgrading from Samba 3 to Samba 4. """
2008-05-22 19:42:18 +04:00
__docformat__ = " restructuredText "
2007-12-10 11:29:00 +03:00
import grp
2007-12-27 12:09:49 +03:00
import ldb
2008-02-09 19:37:42 +03:00
import time
2007-12-10 11:29:00 +03:00
import pwd
2010-01-25 17:17:56 +03:00
from samba import Ldb , registry
2009-07-19 20:51:15 +04:00
from samba . param import LoadParm
2011-09-05 05:07:39 +04:00
from samba . provision import provision , FILL_FULL , ProvisioningError
2011-08-12 05:37:57 +04:00
from samba . samba3 import passdb
from samba . samba3 import param as s3param
2011-09-05 05:10:36 +04:00
from samba . dcerpc import lsa , samr , security
2011-08-18 09:21:32 +04:00
from samba . dcerpc . security import dom_sid
from samba import dsdb
from samba . ndr import ndr_pack
2011-09-07 06:21:00 +04:00
from samba import unix2nttime
2007-12-10 11:29:00 +03:00
2011-08-25 11:20:05 +04:00
def import_sam_policy ( samdb , policy , logger ) :
""" Import a Samba 3 policy.
2010-11-28 16:09:30 +03:00
2011-08-25 11:20:05 +04:00
: param samdb : Samba4 SAM database
: param policy : Samba3 account policy
: param logger : Logger object
"""
2007-12-10 11:29:00 +03:00
2011-08-25 11:20:05 +04:00
# Following entries are used -
# min password length, password history, minimum password age,
# maximum password age, lockout duration
#
# Following entries are not used -
# reset count minutes, user must logon to change password,
# bad lockout minutes, disconnect time
2007-12-10 11:29:00 +03:00
2011-08-25 11:20:05 +04:00
m = ldb . Message ( )
m . dn = samdb . get_default_basedn ( )
2011-09-09 01:31:42 +04:00
m [ ' a01 ' ] = ldb . MessageElement ( str ( policy [ ' min password length ' ] ) , ldb . FLAG_MOD_REPLACE ,
2011-08-25 11:20:05 +04:00
' minPwdLength ' )
m [ ' a02 ' ] = ldb . MessageElement ( str ( policy [ ' password history ' ] ) , ldb . FLAG_MOD_REPLACE ,
' pwdHistoryLength ' )
2011-09-07 06:21:00 +04:00
min_pw_age_unix = policy [ ' minimum password age ' ]
min_pw_age_nt = 0 - unix2nttime ( min_pw_age_unix )
m [ ' a03 ' ] = ldb . MessageElement ( str ( min_pw_age_nt ) , ldb . FLAG_MOD_REPLACE , ' minPwdAge ' )
max_pw_age_unix = policy [ ' maximum password age ' ]
if ( max_pw_age_unix == 0xFFFFFFFF ) :
max_pw_age_nt = 0
else :
max_pw_age_nt = unix2nttime ( max_pw_age_unix )
m [ ' a04 ' ] = ldb . MessageElement ( str ( max_pw_age_nt ) , ldb . FLAG_MOD_REPLACE ,
' maxPwdAge ' )
lockout_duration_mins = policy [ ' lockout duration ' ]
lockout_duration_nt = unix2nttime ( lockout_duration_mins * 60 )
m [ ' a05 ' ] = ldb . MessageElement ( str ( lockout_duration_nt ) , ldb . FLAG_MOD_REPLACE ,
' lockoutDuration ' )
2010-11-28 16:09:30 +03:00
2011-08-25 11:20:05 +04:00
try :
samdb . modify ( m )
except ldb . LdbError , e :
logger . warn ( " Could not set account policy, ( %s ) " , str ( e ) )
2007-12-27 12:09:49 +03:00
2009-11-28 18:59:18 +03:00
2011-08-18 09:21:32 +04:00
def add_idmap_entry ( idmapdb , sid , xid , xid_type , logger ) :
2011-08-22 03:42:13 +04:00
""" Create idmap entry
: param idmapdb : Samba4 IDMAP database
: param sid : user / group sid
: param xid : user / group id
: param xid_type : type of id ( UID / GID )
: param logger : Logger object
"""
2011-08-18 09:21:32 +04:00
# First try to see if we already have this entry
found = False
2011-08-22 03:43:20 +04:00
msg = idmapdb . search ( expression = ' objectSid= %s ' % str ( sid ) )
if msg . count == 1 :
found = True
2011-08-18 09:21:32 +04:00
if found :
try :
m = ldb . Message ( )
2011-09-05 05:09:14 +04:00
m . dn = msg [ 0 ] [ ' dn ' ]
2011-08-18 09:21:32 +04:00
m [ ' xidNumber ' ] = ldb . MessageElement ( str ( xid ) , ldb . FLAG_MOD_REPLACE , ' xidNumber ' )
m [ ' type ' ] = ldb . MessageElement ( xid_type , ldb . FLAG_MOD_REPLACE , ' type ' )
idmapdb . modify ( m )
except ldb . LdbError , e :
logger . warn ( ' Could not modify idmap entry for sid= %s , id= %s , type= %s ( %s ) ' ,
str ( sid ) , str ( xid ) , xid_type , str ( e ) )
else :
try :
idmapdb . add ( { " dn " : " CN= %s " % str ( sid ) ,
" cn " : str ( sid ) ,
" objectClass " : " sidMap " ,
" objectSid " : ndr_pack ( sid ) ,
" type " : xid_type ,
" xidNumber " : str ( xid ) } )
except ldb . LdbError , e :
logger . warn ( ' Could not add idmap entry for sid= %s , id= %s , type= %s ( %s ) ' ,
str ( sid ) , str ( xid ) , xid_type , str ( e ) )
2011-09-04 06:10:36 +04:00
def import_idmap ( idmapdb , samba3 , logger ) :
2007-12-27 12:09:49 +03:00
""" Import idmap data.
2011-08-22 03:42:13 +04:00
: param idmapdb : Samba4 IDMAP database
: param samba3_idmap : Samba3 IDMAP database to import from
: param logger : Logger object
2007-12-27 12:09:49 +03:00
"""
2011-09-04 06:10:36 +04:00
try :
samba3_idmap = samba3 . get_idmap_db ( )
2011-09-09 06:44:56 +04:00
except IOError , e :
logger . warn ( ' Cannot open idmap database, Ignoring: %s ' , str ( e ) )
2011-09-04 06:10:36 +04:00
return
2011-08-18 09:21:32 +04:00
currentxid = max ( samba3_idmap . get_user_hwm ( ) , samba3_idmap . get_group_hwm ( ) )
lowerbound = currentxid
# FIXME: upperbound
m = ldb . Message ( )
m . dn = ldb . Dn ( idmapdb , ' CN=CONFIG ' )
m [ ' lowerbound ' ] = ldb . MessageElement ( str ( lowerbound ) , ldb . FLAG_MOD_REPLACE , ' lowerBound ' )
m [ ' xidNumber ' ] = ldb . MessageElement ( str ( currentxid ) , ldb . FLAG_MOD_REPLACE , ' xidNumber ' )
idmapdb . modify ( m )
for id_type , xid in samba3_idmap . ids ( ) :
if id_type == ' UID ' :
xid_type = ' ID_TYPE_UID '
elif id_type == ' GID ' :
xid_type = ' ID_TYPE_GID '
else :
logger . warn ( ' Wrong type of entry in idmap ( %s ), Ignoring ' , id_type )
continue
sid = samba3_idmap . get_sid ( xid , id_type )
add_idmap_entry ( idmapdb , dom_sid ( sid ) , xid , xid_type , logger )
def add_group_from_mapping_entry ( samdb , groupmap , logger ) :
2011-08-22 03:42:13 +04:00
""" Add or modify group from group mapping entry
param samdb : Samba4 SAM database
param groupmap : Groupmap entry
param logger : Logger object
"""
2011-08-18 09:21:32 +04:00
# First try to see if we already have this entry
try :
msg = samdb . search ( base = ' <SID= %s > ' % str ( groupmap . sid ) , scope = ldb . SCOPE_BASE )
found = True
except ldb . LdbError , ( ecode , emsg ) :
if ecode == ldb . ERR_NO_SUCH_OBJECT :
found = False
else :
raise ldb . LdbError ( ecode , emsg )
if found :
logger . warn ( ' Group already exists sid= %s , groupname= %s existing_groupname= %s , Ignoring. ' ,
str ( groupmap . sid ) , groupmap . nt_name , msg [ 0 ] [ ' sAMAccountName ' ] [ 0 ] )
else :
if groupmap . sid_name_use == lsa . SID_NAME_WKN_GRP :
2011-09-05 05:10:36 +04:00
# In a lot of Samba3 databases, aliases are marked as well known groups
( group_dom_sid , rid ) = group . sid . split ( )
if ( group_dom_sid != security . dom_sid ( security . SID_BUILTIN ) ) :
return
2011-08-18 09:21:32 +04:00
m = ldb . Message ( )
m . dn = ldb . Dn ( samdb , " CN= %s ,CN=Users, %s " % ( groupmap . nt_name , samdb . get_default_basedn ( ) ) )
m [ ' a01 ' ] = ldb . MessageElement ( groupmap . nt_name , ldb . FLAG_MOD_ADD , ' cn ' )
m [ ' a02 ' ] = ldb . MessageElement ( ' group ' , ldb . FLAG_MOD_ADD , ' objectClass ' )
m [ ' a03 ' ] = ldb . MessageElement ( ndr_pack ( groupmap . sid ) , ldb . FLAG_MOD_ADD , ' objectSid ' )
m [ ' a04 ' ] = ldb . MessageElement ( groupmap . comment , ldb . FLAG_MOD_ADD , ' description ' )
m [ ' a05 ' ] = ldb . MessageElement ( groupmap . nt_name , ldb . FLAG_MOD_ADD , ' sAMAccountName ' )
2011-09-05 05:10:36 +04:00
# Fix up incorrect 'well known' groups that are actually builtin (per test above) to be aliases
if groupmap . sid_name_use == lsa . SID_NAME_ALIAS or groupmap . sid_name_use == lsa . SID_NAME_WKN_GRP :
2011-08-18 09:21:32 +04:00
m [ ' a06 ' ] = ldb . MessageElement ( str ( dsdb . GTYPE_SECURITY_DOMAIN_LOCAL_GROUP ) , ldb . FLAG_MOD_ADD , ' groupType ' )
try :
samdb . add ( m , controls = [ " relax:0 " ] )
except ldb . LdbError , e :
logger . warn ( ' Could not add group name= %s ( %s ) ' , groupmap . nt_name , str ( e ) )
2011-08-19 09:53:28 +04:00
def add_users_to_group ( samdb , group , members , logger ) :
2011-08-22 03:42:13 +04:00
""" Add user/member to group/alias
2007-12-10 11:29:00 +03:00
2011-08-22 03:42:13 +04:00
param samdb : Samba4 SAM database
param group : Groupmap object
param members : List of member SIDs
param logger : Logger object
"""
2011-08-18 09:21:32 +04:00
for member_sid in members :
m = ldb . Message ( )
2011-09-05 16:38:15 +04:00
m . dn = ldb . Dn ( samdb , " <SID= %s > " % str ( group . sid ) )
m [ ' a01 ' ] = ldb . MessageElement ( " <SID= %s > " % str ( member_sid ) , ldb . FLAG_MOD_ADD , ' member ' )
2011-08-18 09:21:32 +04:00
try :
samdb . modify ( m )
2011-09-05 12:10:37 +04:00
except ldb . LdbError , ( ecode , emsg ) :
2011-09-06 02:14:35 +04:00
if ecode == ldb . ERR_ENTRY_ALREADY_EXISTS :
logger . info ( " skipped re-adding member ' %s ' to group ' %s ' : %s " , member_sid , group . sid , emsg )
elif ecode == ldb . ERR_NO_SUCH_OBJECT :
raise ProvisioningError ( " Could not add member ' %s ' to group ' %s ' as either group or user record doesn ' t exist: %s " % ( member_sid , group . sid , emsg ) )
2011-09-05 12:10:37 +04:00
else :
2011-09-06 02:14:35 +04:00
raise ProvisioningError ( " Could not add member ' %s ' to group ' %s ' : %s " % ( member_sid , group . sid , emsg ) )
2007-12-10 11:29:00 +03:00
2009-11-28 18:59:18 +03:00
2007-12-27 05:55:05 +03:00
def import_wins ( samba4_winsdb , samba3_winsdb ) :
2007-12-27 12:09:49 +03:00
""" Import settings from a Samba3 WINS database.
2010-11-28 16:09:30 +03:00
2007-12-27 12:09:49 +03:00
: param samba4_winsdb : WINS database to import to
: param samba3_winsdb : WINS database to import from
"""
2007-12-27 05:55:05 +03:00
version_id = 0
for ( name , ( ttl , ips , nb_flags ) ) in samba3_winsdb . items ( ) :
2007-12-17 14:19:45 +03:00
version_id + = 1
2007-12-10 11:29:00 +03:00
2007-12-27 05:55:05 +03:00
type = int ( name . split ( " # " , 1 ) [ 1 ] , 16 )
if type == 0x1C :
2007-12-17 14:19:45 +03:00
rType = 0x2
2007-12-27 05:55:05 +03:00
elif type & 0x80 :
if len ( ips ) > 1 :
2007-12-17 14:19:45 +03:00
rType = 0x2
2007-12-10 11:29:00 +03:00
else :
2007-12-17 14:19:45 +03:00
rType = 0x1
2007-12-10 11:29:00 +03:00
else :
2007-12-27 05:55:05 +03:00
if len ( ips ) > 1 :
2007-12-17 14:19:45 +03:00
rType = 0x3
2007-12-10 11:29:00 +03:00
else :
2007-12-17 14:19:45 +03:00
rType = 0x0
2007-12-10 11:29:00 +03:00
2007-12-27 05:55:05 +03:00
if ttl > time . time ( ) :
2007-12-17 14:19:45 +03:00
rState = 0x0 # active
2007-12-10 11:29:00 +03:00
else :
2007-12-17 14:19:45 +03:00
rState = 0x1 # released
2007-12-10 11:29:00 +03:00
2007-12-27 05:55:05 +03:00
nType = ( ( nb_flags & 0x60 ) >> 5 )
2007-12-10 11:29:00 +03:00
2007-12-27 12:09:49 +03:00
samba4_winsdb . add ( { " dn " : " name= %s ,type=0x %s " % tuple ( name . split ( " # " ) ) ,
2007-12-27 05:55:05 +03:00
" type " : name . split ( " # " ) [ 1 ] ,
" name " : name . split ( " # " ) [ 0 ] ,
" objectClass " : " winsRecord " ,
" recordType " : str ( rType ) ,
" recordState " : str ( rState ) ,
" nodeType " : str ( nType ) ,
2007-12-27 12:09:49 +03:00
" expireTime " : ldb . timestring ( ttl ) ,
2007-12-27 05:55:05 +03:00
" isStatic " : " 0 " ,
" versionID " : str ( version_id ) ,
" address " : ips } )
2008-02-10 00:29:42 +03:00
samba4_winsdb . add ( { " dn " : " cn=VERSION " ,
" cn " : " VERSION " ,
2007-12-27 05:55:05 +03:00
" objectClass " : " winsMaxVersion " ,
" maxVersion " : str ( version_id ) } )
2007-12-10 11:29:00 +03:00
2007-12-27 12:09:49 +03:00
def enable_samba3sam ( samdb , ldapurl ) :
""" Enable Samba 3 LDAP URL database.
: param samdb : SAM Database .
: param ldapurl : Samba 3 LDAP URL
"""
samdb . modify_ldif ( """
dn : @MODULES
changetype : modify
replace : @LIST
@LIST : samldb , operational , objectguid , rdn_name , samba3sam
""" )
samdb . add ( { " dn " : " @MAP=samba3sam " , " @MAP_URL " : ldapurl } )
2009-11-28 18:59:18 +03:00
2007-12-10 11:29:00 +03:00
smbconf_keep = [
2010-11-28 16:09:30 +03:00
" dos charset " ,
2007-12-17 14:19:45 +03:00
" unix charset " ,
" display charset " ,
" comment " ,
" path " ,
" directory " ,
" workgroup " ,
" realm " ,
" netbios name " ,
" netbios aliases " ,
" netbios scope " ,
" server string " ,
" interfaces " ,
" bind interfaces only " ,
" security " ,
" auth methods " ,
" encrypt passwords " ,
" null passwords " ,
" obey pam restrictions " ,
" password server " ,
" smb passwd file " ,
" private dir " ,
" passwd chat " ,
" password level " ,
" lanman auth " ,
" ntlm auth " ,
" client NTLMv2 auth " ,
" client lanman auth " ,
" client plaintext auth " ,
" read only " ,
" hosts allow " ,
" hosts deny " ,
" log level " ,
" debuglevel " ,
" log file " ,
" smb ports " ,
" large readwrite " ,
" max protocol " ,
" min protocol " ,
" unicode " ,
" read raw " ,
" write raw " ,
" disable netbios " ,
" nt status support " ,
" max mux " ,
" max xmit " ,
" name resolve order " ,
" max wins ttl " ,
" min wins ttl " ,
" time server " ,
" unix extensions " ,
" use spnego " ,
" server signing " ,
" client signing " ,
" max connections " ,
" paranoid server security " ,
" socket options " ,
" strict sync " ,
" max print jobs " ,
" printable " ,
" print ok " ,
" printer name " ,
" printer " ,
" map system " ,
" map hidden " ,
" map archive " ,
" preferred master " ,
" prefered master " ,
" local master " ,
" browseable " ,
" browsable " ,
" wins server " ,
" wins support " ,
" csc policy " ,
" strict locking " ,
" preload " ,
" auto services " ,
" lock dir " ,
" lock directory " ,
" pid directory " ,
" socket address " ,
" copy " ,
" include " ,
" available " ,
" volume " ,
" fstype " ,
" panic action " ,
" msdfs root " ,
" host msdfs " ,
" winbind separator " ]
2007-12-10 11:29:00 +03:00
def upgrade_smbconf ( oldconf , mark ) :
2007-12-17 14:19:45 +03:00
""" Remove configuration variables not present in Samba4
: param oldconf : Old configuration structure
2010-11-28 16:09:30 +03:00
: param mark : Whether removed configuration variables should be
2007-12-17 14:19:45 +03:00
kept in the new configuration as " samba3:<name> "
"""
data = oldconf . data ( )
2009-07-19 20:51:15 +04:00
newconf = LoadParm ( )
2007-12-17 14:19:45 +03:00
for s in data :
for p in data [ s ] :
keep = False
for k in smbconf_keep :
2007-12-10 11:29:00 +03:00
if smbconf_keep [ k ] == p :
2007-12-17 14:19:45 +03:00
keep = True
break
2007-12-10 11:29:00 +03:00
if keep :
2007-12-17 14:19:45 +03:00
newconf . set ( s , p , oldconf . get ( s , p ) )
2007-12-10 11:29:00 +03:00
elif mark :
2007-12-17 14:19:45 +03:00
newconf . set ( s , " samba3: " + p , oldconf . get ( s , p ) )
2007-12-10 11:29:00 +03:00
2007-12-17 14:19:45 +03:00
return newconf
2007-12-10 11:29:00 +03:00
2007-12-27 05:55:05 +03:00
SAMBA3_PREDEF_NAMES = {
' HKLM ' : registry . HKEY_LOCAL_MACHINE ,
}
def import_registry ( samba4_registry , samba3_regdb ) :
""" Import a Samba 3 registry database into the Samba 4 registry.
: param samba4_registry : Samba 4 registry handle .
: param samba3_regdb : Samba 3 registry database handle .
"""
def ensure_key_exists ( keypath ) :
( predef_name , keypath ) = keypath . split ( " / " , 1 )
predef_id = SAMBA3_PREDEF_NAMES [ predef_name ]
keypath = keypath . replace ( " / " , " \\ " )
return samba4_registry . create_key ( predef_id , keypath )
for key in samba3_regdb . keys ( ) :
key_handle = ensure_key_exists ( key )
for subkey in samba3_regdb . subkeys ( key ) :
ensure_key_exists ( subkey )
for ( value_name , ( value_type , value_data ) ) in samba3_regdb . values ( key ) . items ( ) :
key_handle . set_value ( value_name , value_type , value_data )
2011-09-05 05:07:39 +04:00
def upgrade_from_samba3 ( samba3 , logger , targetdir , session_info = None , useeadb = False ) :
2011-08-12 05:37:57 +04:00
""" Upgrade from samba3 database to samba4 AD database
2011-08-25 11:20:05 +04:00
: param samba3 : samba3 object
: param logger : Logger object
: param targetdir : samba4 database directory
: param session_info : Session information
"""
2009-11-27 17:50:26 +03:00
2011-08-25 11:20:05 +04:00
if samba3 . lp . get ( " domain logons " ) :
2009-11-27 17:50:26 +03:00
serverrole = " domain controller "
else :
2011-08-25 11:20:05 +04:00
if samba3 . lp . get ( " security " ) == " user " :
2009-11-27 17:50:26 +03:00
serverrole = " standalone "
else :
serverrole = " member server "
2011-08-25 11:20:05 +04:00
domainname = samba3 . lp . get ( " workgroup " )
realm = samba3 . lp . get ( " realm " )
netbiosname = samba3 . lp . get ( " netbios name " )
2009-11-27 17:50:26 +03:00
2011-08-12 05:37:57 +04:00
# secrets db
2009-11-27 17:50:26 +03:00
secrets_db = samba3 . get_secrets_db ( )
2010-11-28 16:09:30 +03:00
2011-08-12 05:37:57 +04:00
if not domainname :
2009-11-27 17:50:26 +03:00
domainname = secrets_db . domains ( ) [ 0 ]
2011-08-25 11:20:05 +04:00
logger . warning ( " No workgroup specified in smb.conf file, assuming ' %s ' " ,
2010-06-13 17:05:50 +04:00
domainname )
2010-11-28 16:09:30 +03:00
2011-08-12 05:37:57 +04:00
if not realm :
2011-08-25 11:20:05 +04:00
if serverrole == " domain controller " :
2011-09-05 05:07:39 +04:00
raise ProvisioningError ( " No realm specified in smb.conf file and being a DC. That upgrade path doesn ' t work! Please add a ' realm ' directive to your old smb.conf to let us know which one you want to use (it is the DNS name of the AD domain you wish to create. " )
2009-11-27 17:50:26 +03:00
else :
realm = domainname . upper ( )
2010-06-13 17:05:50 +04:00
logger . warning ( " No realm specified in smb.conf file, assuming ' %s ' " ,
realm )
2009-11-27 17:50:26 +03:00
2011-08-12 05:37:57 +04:00
# Find machine account and password
machinepass = None
2011-08-13 07:32:18 +04:00
machinerid = None
2011-08-12 05:37:57 +04:00
machinesid = None
2011-08-13 07:32:18 +04:00
next_rid = 1000
2011-08-12 05:37:57 +04:00
try :
machinepass = secrets_db . get_machine_password ( netbiosname )
except :
pass
# We must close the direct pytdb database before the C code loads it
secrets_db . close ( )
2011-08-25 11:20:05 +04:00
# Connect to old password backend
passdb . set_secrets_dir ( samba3 . lp . get ( " private dir " ) )
s3db = samba3 . get_sam_db ( )
2011-08-12 05:37:57 +04:00
2011-08-18 09:21:32 +04:00
# Get domain sid
2011-08-12 05:37:57 +04:00
try :
2011-08-18 09:21:32 +04:00
domainsid = passdb . get_global_sam_sid ( )
2011-08-22 03:43:20 +04:00
except passdb . error :
2011-08-18 09:21:32 +04:00
raise Exception ( " Can ' t find domain sid for ' %s ' , Exiting. " % domainname )
2011-08-12 05:37:57 +04:00
2011-08-18 09:21:32 +04:00
# Get machine account, sid, rid
2011-08-12 05:37:57 +04:00
try :
2011-08-25 11:20:05 +04:00
machineacct = s3db . getsampwnam ( ' %s $ ' % netbiosname )
2011-08-12 05:37:57 +04:00
machinesid , machinerid = machineacct . user_sid . split ( )
except :
pass
2011-08-25 11:20:05 +04:00
# Export account policy
logger . info ( " Exporting account policy " )
policy = s3db . get_account_policy ( )
2011-08-18 09:21:32 +04:00
2011-08-25 11:20:05 +04:00
# Export groups from old passdb backend
2011-08-18 09:21:32 +04:00
logger . info ( " Exporting groups " )
2011-08-25 11:20:05 +04:00
grouplist = s3db . enum_group_mapping ( )
2011-08-18 09:21:32 +04:00
groupmembers = { }
for group in grouplist :
sid , rid = group . sid . split ( )
if sid == domainsid :
if rid > = next_rid :
next_rid = rid + 1
# Get members for each group/alias
2011-09-04 05:58:34 +04:00
if group . sid_name_use == lsa . SID_NAME_ALIAS :
2011-08-25 11:20:05 +04:00
members = s3db . enum_aliasmem ( group . sid )
2011-08-18 09:21:32 +04:00
elif group . sid_name_use == lsa . SID_NAME_DOM_GRP :
try :
2011-08-25 11:20:05 +04:00
members = s3db . enum_group_members ( group . sid )
2011-08-18 09:21:32 +04:00
except :
continue
2011-09-05 05:10:36 +04:00
groupmembers [ group . nt_name ] = members
2011-09-04 05:58:34 +04:00
elif group . sid_name_use == lsa . SID_NAME_WKN_GRP :
2011-09-05 05:10:36 +04:00
( group_dom_sid , rid ) = group . sid . split ( )
if ( group_dom_sid != security . dom_sid ( security . SID_BUILTIN ) ) :
logger . warn ( " Ignoring ' well known ' group ' %s ' (should already be in AD, and have no members) " ,
group . nt_name )
continue
# A number of buggy databases mix up well known groups and aliases.
members = s3db . enum_aliasmem ( group . sid )
2011-08-18 09:21:32 +04:00
else :
logger . warn ( " Ignoring group ' %s ' with sid_name_use= %d " ,
group . nt_name , group . sid_name_use )
continue
2010-11-28 16:09:30 +03:00
2011-08-25 11:20:05 +04:00
# Export users from old passdb backend
2011-08-18 09:21:32 +04:00
logger . info ( " Exporting users " )
2011-08-25 11:20:05 +04:00
userlist = s3db . search_users ( 0 )
2011-08-12 05:37:57 +04:00
userdata = { }
2011-08-18 09:21:32 +04:00
uids = { }
2011-08-19 09:53:28 +04:00
admin_user = None
2011-08-12 05:37:57 +04:00
for entry in userlist :
2011-08-13 07:32:18 +04:00
if machinerid and machinerid == entry [ ' rid ' ] :
2011-08-12 05:37:57 +04:00
continue
username = entry [ ' account_name ' ]
if entry [ ' rid ' ] < 1000 :
2011-08-18 09:21:32 +04:00
logger . info ( " Skipping wellknown rid= %d (for username= %s ) " , entry [ ' rid ' ] , username )
2011-08-12 05:37:57 +04:00
continue
2011-08-13 07:32:18 +04:00
if entry [ ' rid ' ] > = next_rid :
next_rid = entry [ ' rid ' ] + 1
2011-09-05 05:10:36 +04:00
user = s3db . getsampwnam ( username )
acct_type = ( user . acct_ctrl & ( samr . ACB_NORMAL | samr . ACB_WSTRUST | samr . ACB_SVRTRUST | samr . ACB_DOMTRUST ) )
if ( acct_type == samr . ACB_NORMAL or acct_type == samr . ACB_WSTRUST or acct_type == samr . ACB_SVRTRUST ) :
pass
elif acct_type == samr . ACB_DOMTRUST :
logger . warn ( " Skipping inter-domain trust from domain %s , this trust must be re-created as an AD trust " % username [ : - 1 ] )
continue
elif acct_type == ( samr . ACB_NORMAL | samr . ACB_WSTRUST ) and username [ - 1 ] == ' $ ' :
logger . warn ( " Fixing account %s which had both ACB_NORMAL (U) and ACB_WSTRUST (W) set. Account will be marked as ACB_WSTRUST (W), i.e. as a domain member " % username )
user . acct_ctrl = ( user . acct_ctrl & ~ samr . ACB_NORMAL )
else :
raise ProvisioningError ( """ Failed to upgrade due to invalid account %s , account control flags 0x %08X must have exactly one of
ACB_NORMAL ( N , 0 x % 08 X ) , ACB_WSTRUST ( W 0 x % 08 X ) , ACB_SVRTRUST ( S 0 x % 08 X ) or ACB_DOMTRUST ( D 0 x % 08 X ) .
Please fix this account before attempting to upgrade again
"""
% ( user . acct_flags , username ,
samr . ACB_NORMAL , samr . ACB_WSTRUST , samr . ACB_SVRTRUST , samr . ACB_DOMTRUST ) )
2011-08-13 07:32:18 +04:00
2011-09-05 05:10:36 +04:00
userdata [ username ] = user
2011-08-18 09:21:32 +04:00
try :
2011-09-05 05:10:36 +04:00
uids [ username ] = s3db . sid_to_id ( user . user_sid ) [ 0 ]
2011-08-18 09:21:32 +04:00
except :
try :
uids [ username ] = pwd . getpwnam ( username ) . pw_uid
except :
pass
2011-08-19 09:53:28 +04:00
if not admin_user and username . lower ( ) == ' root ' :
admin_user = username
if username . lower ( ) == ' administrator ' :
admin_user = username
2011-08-18 09:21:32 +04:00
logger . info ( " Next rid = %d " , next_rid )
2011-08-12 05:37:57 +04:00
# Do full provision
result = provision ( logger , session_info , None ,
2009-11-27 17:50:26 +03:00
targetdir = targetdir , realm = realm , domain = domainname ,
2011-08-18 09:21:32 +04:00
domainsid = str ( domainsid ) , next_rid = next_rid ,
2011-08-13 07:32:18 +04:00
dc_rid = machinerid ,
2009-11-27 17:50:26 +03:00
hostname = netbiosname , machinepass = machinepass ,
2011-09-05 05:07:39 +04:00
serverrole = serverrole , samdb_fill = FILL_FULL ,
useeadb = useeadb )
2009-11-27 17:50:26 +03:00
2011-08-25 11:20:05 +04:00
# Import WINS database
logger . info ( " Importing WINS database " )
2009-11-28 17:28:45 +03:00
import_wins ( Ldb ( result . paths . winsdb ) , samba3 . get_wins_db ( ) )
2009-11-27 17:50:26 +03:00
2011-08-25 11:20:05 +04:00
# Set Account policy
logger . info ( " Importing Account policy " )
import_sam_policy ( result . samdb , policy , logger )
2009-11-27 17:50:26 +03:00
2011-08-25 11:20:05 +04:00
# Migrate IDMAP database
logger . info ( " Importing idmap database " )
2011-09-04 06:10:36 +04:00
import_idmap ( result . idmap , samba3 , logger )
2011-08-18 09:21:32 +04:00
2011-08-25 11:20:05 +04:00
# Set the s3 context for samba4 configuration
new_lp_ctx = s3param . get_context ( )
new_lp_ctx . load ( result . lp . configfile )
new_lp_ctx . set ( " private dir " , result . lp . get ( " private dir " ) )
new_lp_ctx . set ( " state directory " , result . lp . get ( " state directory " ) )
2011-08-26 04:01:29 +04:00
new_lp_ctx . set ( " lock directory " , result . lp . get ( " lock directory " ) )
2011-08-25 11:20:05 +04:00
2011-08-18 09:21:32 +04:00
# Connect to samba4 backend
2011-08-25 11:20:05 +04:00
s4_passdb = passdb . PDB ( new_lp_ctx . get ( " passdb backend " ) )
2009-11-27 17:50:26 +03:00
2011-08-18 09:21:32 +04:00
# Export groups to samba4 backend
logger . info ( " Importing groups " )
for g in grouplist :
# Ignore uninitialized groups (gid = -1)
if g . gid != 0xffffffff :
add_idmap_entry ( result . idmap , g . sid , g . gid , " GID " , logger )
add_group_from_mapping_entry ( result . samdb , g , logger )
# Export users to samba4 backend
logger . info ( " Importing users " )
2011-08-12 05:37:57 +04:00
for username in userdata :
2011-08-19 06:33:15 +04:00
if username . lower ( ) == ' administrator ' or username . lower ( ) == ' root ' :
continue
2011-08-25 11:20:05 +04:00
s4_passdb . add_sam_account ( userdata [ username ] )
2011-08-18 09:21:32 +04:00
if username in uids :
add_idmap_entry ( result . idmap , userdata [ username ] . user_sid , uids [ username ] , " UID " , logger )
logger . info ( " Adding users to groups " )
for g in grouplist :
if g . nt_name in groupmembers :
2011-08-19 09:53:28 +04:00
add_users_to_group ( result . samdb , g , groupmembers [ g . nt_name ] , logger )
# Set password for administrator
if admin_user :
logger . info ( " Setting password for administrator " )
2011-08-25 11:20:05 +04:00
admin_userdata = s4_passdb . getsampwnam ( " administrator " )
2011-08-19 09:53:28 +04:00
admin_userdata . nt_passwd = userdata [ admin_user ] . nt_passwd
if userdata [ admin_user ] . lanman_passwd :
admin_userdata . lanman_passwd = userdata [ admin_user ] . lanman_passwd
admin_userdata . pass_last_set_time = userdata [ admin_user ] . pass_last_set_time
if userdata [ admin_user ] . pw_history :
admin_userdata . pw_history = userdata [ admin_user ] . pw_history
2011-08-25 11:20:05 +04:00
s4_passdb . update_sam_account ( admin_userdata )
2011-08-19 09:53:28 +04:00
logger . info ( " Administrator password has been set to password of user ' %s ' " , admin_user )
2011-08-18 09:21:32 +04:00
# FIXME: import_registry(registry.Registry(), samba3.get_registry())
2011-08-25 11:20:05 +04:00
# FIXME: shares