2007-12-10 11:29:00 +03:00
#!/usr/bin/python
#
# backend code for upgrading from Samba3
# Copyright Jelmer Vernooij 2005-2007
# Released under the GNU GPL v3 or later
#
""" Support code for upgrading from Samba 3 to Samba 4. """
2008-01-25 03:02:13 +03:00
from provision import findnss , provision , FILL_DRS
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
2007-12-17 14:19:45 +03:00
import uuid
2007-12-27 05:55:05 +03:00
import registry
2007-12-27 12:09:49 +03:00
from samba import Ldb
from samba . samdb import SamDB
2007-12-10 11:29:00 +03:00
2007-12-27 12:09:49 +03:00
def import_sam_policy ( samldb , samba3_policy , domaindn ) :
2008-02-10 00:29:42 +03:00
""" Import a Samba 3 policy database. """
2007-12-27 12:09:49 +03:00
samldb . modify_ldif ( """
2007-12-10 11:29:00 +03:00
dn : % s
changetype : modify
replace : minPwdLength
minPwdLength : % d
pwdHistoryLength : % d
minPwdAge : % d
maxPwdAge : % d
lockoutDuration : % d
samba3ResetCountMinutes : % d
samba3UserMustLogonToChangePassword : % d
samba3BadLockoutMinutes : % d
samba3DisconnectTime : % d
2007-12-24 04:19:41 +03:00
""" % (dn, policy.min_password_length,
policy . password_history , policy . minimum_password_age ,
policy . maximum_password_age , policy . lockout_duration ,
policy . reset_count_minutes , policy . user_must_logon_to_change_password ,
2007-12-27 12:09:49 +03:00
policy . bad_lockout_minutes , policy . disconnect_time ) )
2007-12-10 11:29:00 +03:00
2007-12-27 12:09:49 +03:00
def import_sam_account ( samldb , acc , domaindn , domainsid ) :
""" Import a Samba 3 SAM account.
: param samldb : Samba 4 SAM Database handle
: param acc : Samba 3 account
: param domaindn : Domain DN
: param domainsid : Domain SID . """
2007-12-10 11:29:00 +03:00
if acc . nt_username is None or acc . nt_username == " " :
2007-12-17 14:19:45 +03:00
acc . nt_username = acc . username
2007-12-10 11:29:00 +03:00
if acc . fullname is None :
2007-12-27 12:09:49 +03:00
try :
acc . fullname = pwd . getpwnam ( acc . username ) [ 4 ] . split ( " , " ) [ 0 ]
except KeyError :
pass
2007-12-10 11:29:00 +03:00
if acc . fullname is None :
2007-12-17 14:19:45 +03:00
acc . fullname = acc . username
assert acc . fullname is not None
assert acc . nt_username is not None
2007-12-10 11:29:00 +03:00
2007-12-27 12:09:49 +03:00
samldb . add ( {
" dn " : " cn= %s , %s " % ( acc . fullname , domaindn ) ,
" objectClass " : [ " top " , " user " ] ,
" lastLogon " : str ( acc . logon_time ) ,
" lastLogoff " : str ( acc . logoff_time ) ,
" unixName " : acc . username ,
" sAMAccountName " : acc . nt_username ,
" cn " : acc . nt_username ,
" description " : acc . acct_desc ,
" primaryGroupID " : str ( acc . group_rid ) ,
" badPwdcount " : str ( acc . bad_password_count ) ,
" logonCount " : str ( acc . logon_count ) ,
" samba3Domain " : acc . domain ,
" samba3DirDrive " : acc . dir_drive ,
" samba3MungedDial " : acc . munged_dial ,
" samba3Homedir " : acc . homedir ,
" samba3LogonScript " : acc . logon_script ,
" samba3ProfilePath " : acc . profile_path ,
" samba3Workstations " : acc . workstations ,
" samba3KickOffTime " : str ( acc . kickoff_time ) ,
" samba3BadPwdTime " : str ( acc . bad_password_time ) ,
" samba3PassLastSetTime " : str ( acc . pass_last_set_time ) ,
" samba3PassCanChangeTime " : str ( acc . pass_can_change_time ) ,
" samba3PassMustChangeTime " : str ( acc . pass_must_change_time ) ,
" objectSid " : " %s - %d " % ( domainsid , acc . user_rid ) ,
" lmPwdHash: " : acc . lm_password ,
" ntPwdHash: " : acc . nt_password ,
} )
def import_sam_group ( samldb , sid , gid , sid_name_use , nt_name , comment , domaindn ) :
""" Upgrade a SAM group.
: param samldb : SAM database .
: param gid : Group GID
: param sid_name_use : SID name use
: param nt_name : NT Group Name
: param comment : NT Group Comment
: param domaindn : Domain DN
"""
if sid_name_use == 5 : # Well-known group
2007-12-17 14:19:45 +03:00
return None
2007-12-10 11:29:00 +03:00
2007-12-27 12:09:49 +03:00
if nt_name in ( " Domain Guests " , " Domain Users " , " Domain Admins " ) :
2007-12-17 14:19:45 +03:00
return None
2007-12-27 12:09:49 +03:00
if gid == - 1 :
gr = grp . getgrnam ( nt_name )
2007-12-10 11:29:00 +03:00
else :
2007-12-27 12:09:49 +03:00
gr = grp . getgrgid ( gid )
2007-12-10 11:29:00 +03:00
if gr is None :
2007-12-27 12:09:49 +03:00
unixname = " UNKNOWN "
2007-12-10 11:29:00 +03:00
else :
2007-12-27 12:09:49 +03:00
unixname = gr . gr_name
2007-12-10 11:29:00 +03:00
2007-12-27 12:09:49 +03:00
assert unixname is not None
2007-12-17 14:19:45 +03:00
2007-12-27 12:09:49 +03:00
samldb . add ( {
" dn " : " cn= %s , %s " % ( nt_name , domaindn ) ,
" objectClass " : [ " top " , " group " ] ,
" description " : comment ,
" cn " : nt_name ,
" objectSid " : sid ,
" unixName " : unixname ,
" samba3SidNameUse " : str ( sid_name_use )
} )
def import_idmap ( samdb , samba3_idmap , domaindn ) :
""" Import idmap data.
: param samdb : SamDB handle .
: param samba3_idmap : Samba 3 IDMAP database to import from
: param domaindn : Domain DN .
"""
samdb . add ( {
2007-12-27 05:55:05 +03:00
" dn " : domaindn ,
" userHwm " : str ( samba3_idmap . get_user_hwm ( ) ) ,
" groupHwm " : str ( samba3_idmap . get_group_hwm ( ) ) } )
2007-12-10 11:29:00 +03:00
2007-12-27 05:55:05 +03:00
for uid in samba3_idmap . uids ( ) :
2007-12-27 12:09:49 +03:00
samdb . add ( { " dn " : " SID= %s , %s " % ( samba3_idmap . get_user_sid ( uid ) , domaindn ) ,
2007-12-27 05:55:05 +03:00
" SID " : samba3_idmap . get_user_sid ( uid ) ,
" type " : " user " ,
" unixID " : str ( uid ) } )
2007-12-10 11:29:00 +03:00
2007-12-27 05:55:05 +03:00
for gid in samba3_idmap . uids ( ) :
2007-12-27 12:09:49 +03:00
samdb . add ( { " dn " : " SID= %s , %s " % ( samba3_idmap . get_group_sid ( gid ) , domaindn ) ,
2007-12-27 05:55:05 +03:00
" SID " : samba3_idmap . get_group_sid ( gid ) ,
" type " : " group " ,
" unixID " : str ( gid ) } )
2007-12-10 11:29:00 +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.
: 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-26 01:36:44 +03:00
def upgrade_provision ( samba3 , setup_dir , message , credentials , session_info , lp , paths ) :
2007-12-26 01:36:31 +03:00
oldconf = samba3 . get_conf ( )
if oldconf . get ( " domain logons " ) == " True " :
serverrole = " domain controller "
else :
if oldconf . get ( " security " ) == " user " :
serverrole = " standalone "
else :
serverrole = " member server "
domainname = oldconf . get ( " workgroup " )
2007-12-26 01:36:44 +03:00
if domainname :
domainname = str ( domainname )
2007-12-26 01:36:31 +03:00
realm = oldconf . get ( " realm " )
netbiosname = oldconf . get ( " netbios name " )
secrets_db = samba3 . get_secrets_db ( )
2007-12-17 14:19:45 +03:00
2007-12-10 11:29:00 +03:00
if domainname is None :
2007-12-26 01:36:31 +03:00
domainname = secrets_db . domains ( ) [ 0 ]
message ( " No domain specified in smb.conf file, assuming ' %s ' " % domainname )
2007-12-17 14:19:45 +03:00
2007-12-10 11:29:00 +03:00
if realm is None :
2007-12-26 01:36:31 +03:00
realm = domainname . lower ( )
message ( " No realm specified in smb.conf file, assuming ' %s ' \n " % realm )
2007-12-10 11:29:00 +03:00
2007-12-26 01:36:31 +03:00
domainguid = secrets_db . get_domain_guid ( domainname )
2007-12-26 01:36:44 +03:00
domainsid = secrets_db . get_sid ( domainname )
2007-12-26 01:36:31 +03:00
if domainsid is None :
message ( " Can ' t find domain secrets for ' %s ' ; using random SID \n " % domainname )
if netbiosname is not None :
machinepass = secrets_db . get_machine_password ( netbiosname )
2007-12-10 11:29:00 +03:00
else :
2007-12-26 01:36:44 +03:00
machinepass = None
2007-12-17 14:19:45 +03:00
2008-03-07 02:57:52 +03:00
domaindn = provision ( setup_dir = setup_dir , message = message ,
2008-02-09 05:59:45 +03:00
samdb_fill = FILL_DRS , paths = paths , session_info = session_info ,
credentials = credentials , realm = realm ,
2007-12-27 12:09:49 +03:00
domain = domainname , domainsid = domainsid , domainguid = domainguid ,
machinepass = machinepass , serverrole = serverrole )
samdb = SamDB ( paths . samdb , credentials = credentials , lp = lp , session_info = session_info )
import_wins ( Ldb ( paths . winsdb ) , samba3 . get_wins_db ( ) )
# FIXME: import_registry(registry.Registry(), samba3.get_registry())
# FIXME: import_idmap(samdb,samba3.get_idmap_db(),domaindn)
groupdb = samba3 . get_groupmapping_db ( )
for sid in groupdb . groupsids ( ) :
( gid , sid_name_use , nt_name , comment ) = groupdb . get_group ( sid )
# FIXME: import_sam_group(samdb, sid, gid, sid_name_use, nt_name, comment, domaindn)
# FIXME: Aliases
passdb = samba3 . get_sam_db ( )
for name in passdb :
user = passdb [ name ]
#FIXME: import_sam_account(samdb, user, domaindn, domainsid)
if hasattr ( passdb , ' ldap_url ' ) :
message ( " Enabling Samba3 LDAP mappings for SAM database " )
enable_samba3sam ( samdb , passdb . ldap_url )
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 } )
2007-12-10 11:29:00 +03:00
smbconf_keep = [
2007-12-17 14:19:45 +03:00
" dos charset " ,
" 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 " ,
" announce version " ,
" announce as " ,
" 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
: param mark : Whether removed configuration variables should be
kept in the new configuration as " samba3:<name> "
"""
data = oldconf . data ( )
newconf = param_init ( )
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 )