2007-12-17 10:20:20 +03:00
#!/usr/bin/python
# Unix SMB/CIFS implementation.
2008-01-25 03:02:13 +03:00
# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
2007-12-17 10:20:20 +03:00
#
# Based on the original in EJS:
2008-01-25 03:02:13 +03:00
# Copyright (C) Andrew Tridgell <tridge@samba.org> 2005
2007-12-17 10:20:20 +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-30 03:14:15 +03:00
""" Convenience functions for using the SAM. """
2007-12-17 10:20:20 +03:00
import samba
2007-12-17 14:07:51 +03:00
import misc
2007-12-18 04:21:14 +03:00
import ldb
2008-04-14 13:51:02 +04:00
from samba . idmap import IDmapDB
import pwd
2007-12-17 10:20:20 +03:00
2008-05-22 19:42:18 +04:00
__docformat__ = " restructuredText "
2007-12-17 10:20:20 +03:00
class SamDB ( samba . Ldb ) :
2007-12-30 03:14:15 +03:00
""" The SAM database. """
2008-04-14 13:51:02 +04:00
2007-12-18 04:21:28 +03:00
def __init__ ( self , url = None , session_info = None , credentials = None ,
modules_dir = None , lp = None ) :
2007-12-30 03:14:15 +03:00
""" Open the Sam Database.
: param url : URL of the database .
"""
2008-04-14 13:51:02 +04:00
self . lp = lp
2007-12-18 04:21:28 +03:00
super ( SamDB , self ) . __init__ ( session_info = session_info , credentials = credentials ,
modules_dir = modules_dir , lp = lp )
2007-12-20 01:27:38 +03:00
assert misc . dsdb_set_global_schema ( self ) == 0
2007-12-18 04:21:28 +03:00
if url :
self . connect ( url )
2008-04-14 13:51:02 +04:00
else :
self . connect ( lp . get ( " sam database " ) )
def connect ( self , url ) :
super ( SamDB , self ) . connect ( misc . private_path ( self . lp , url ) )
2007-12-18 04:21:14 +03:00
2007-12-17 10:20:20 +03:00
def add_foreign ( self , domaindn , sid , desc ) :
""" Add a foreign security principle. """
add = """
dn : CN = % s , CN = ForeignSecurityPrincipals , % s
objectClass : top
objectClass : foreignSecurityPrincipal
description : % s
""" % (sid, domaindn, desc)
# deliberately ignore errors from this, as the records may
# already exist
for msg in self . parse_ldif ( add ) :
self . add ( msg [ 1 ] )
def enable_account ( self , user_dn ) :
2007-12-30 03:14:15 +03:00
""" Enable an account.
2007-12-17 10:20:20 +03:00
: param user_dn : Dn of the account to enable .
"""
2008-03-28 04:08:54 +03:00
res = self . search ( user_dn , ldb . SCOPE_BASE , None , [ " userAccountControl " ] )
2007-12-17 10:20:20 +03:00
assert len ( res ) == 1
2008-03-28 04:08:54 +03:00
userAccountControl = res [ 0 ] [ " userAccountControl " ] [ 0 ]
userAccountControl = int ( userAccountControl )
if ( userAccountControl & 0x2 ) :
userAccountControl = userAccountControl & ~ 0x2 # remove disabled bit
if ( userAccountControl & 0x20 ) :
userAccountControl = userAccountControl & ~ 0x20 # remove 'no password required' bit
2007-12-17 10:20:20 +03:00
mod = """
dn : % s
changetype : modify
replace : userAccountControl
userAccountControl : % u
""" % (user_dn, userAccountControl)
2007-12-30 03:14:15 +03:00
self . modify_ldif ( mod )
2007-12-17 10:20:20 +03:00
2007-12-30 03:14:15 +03:00
def newuser ( self , username , unixname , password ) :
""" add a new user record.
: param username : Name of the new user .
: param unixname : Name of the unix user to map to .
: param password : Password for the new user
"""
2007-12-17 10:20:20 +03:00
# connect to the sam
self . transaction_start ( )
# find the DNs for the domain and the domain users group
2008-02-13 03:21:06 +03:00
res = self . search ( " " , scope = ldb . SCOPE_BASE ,
expression = " (defaultNamingContext=*) " ,
attrs = [ " defaultNamingContext " ] )
2008-03-28 04:08:54 +03:00
assert ( len ( res ) == 1 and res [ 0 ] [ " defaultNamingContext " ] is not None )
2008-01-11 18:13:46 +03:00
domain_dn = res [ 0 ] [ " defaultNamingContext " ] [ 0 ]
2007-12-17 10:20:20 +03:00
assert ( domain_dn is not None )
user_dn = " CN= %s ,CN=Users, %s " % ( username , domain_dn )
#
# the new user record. note the reliance on the samdb module to fill
# in a sid, guid etc
#
2007-12-30 03:14:15 +03:00
# now the real work
self . add ( { " dn " : user_dn ,
" sAMAccountName " : username ,
" sambaPassword " : password ,
" objectClass " : " user " } )
2008-04-14 13:51:02 +04:00
res = self . search ( user_dn , scope = ldb . SCOPE_BASE ,
expression = " objectclass=* " ,
attrs = [ " objectSid " ] )
assert ( len ( res ) == 1 )
user_sid = self . schema_format_value ( " objectSid " , res [ 0 ] [ " objectSid " ] [ 0 ] )
try :
idmap = IDmapDB ( lp = self . lp )
user = pwd . getpwnam ( unixname )
# setup ID mapping for this UID
idmap . setup_name_mapping ( user_sid , idmap . TYPE_UID , user [ 2 ] )
except KeyError :
pass
2008-03-28 04:08:54 +03:00
# modify the userAccountControl to remove the disabled bit
self . enable_account ( user_dn )
self . transaction_commit ( )
def setpassword ( self , filter , password ) :
""" Set a password on a user record
: param filter : LDAP filter to find the user ( eg samccountname = name )
: param password : Password for the user
"""
# connect to the sam
self . transaction_start ( )
# find the DNs for the domain
res = self . search ( " " , scope = ldb . SCOPE_BASE ,
expression = " (defaultNamingContext=*) " ,
attrs = [ " defaultNamingContext " ] )
assert ( len ( res ) == 1 and res [ 0 ] [ " defaultNamingContext " ] is not None )
domain_dn = res [ 0 ] [ " defaultNamingContext " ] [ 0 ]
assert ( domain_dn is not None )
res = self . search ( domain_dn , scope = ldb . SCOPE_SUBTREE ,
expression = filter ,
attrs = [ ] )
assert ( len ( res ) == 1 )
user_dn = res [ 0 ] . dn
setpw = """
2007-12-17 10:20:20 +03:00
dn : % s
changetype : modify
2008-03-28 04:08:54 +03:00
replace : sambaPassword
sambaPassword : % s
""" % (user_dn, password)
2007-12-17 10:20:20 +03:00
2008-03-28 04:08:54 +03:00
self . modify_ldif ( setpw )
2007-12-17 10:20:20 +03:00
# modify the userAccountControl to remove the disabled bit
2008-03-28 04:08:54 +03:00
self . enable_account ( user_dn )
2007-12-17 10:20:20 +03:00
self . transaction_commit ( )
2007-12-17 14:07:51 +03:00
def set_domain_sid ( self , sid ) :
2007-12-30 03:14:15 +03:00
""" Change the domain SID used by this SamDB.
: param sid : The new domain sid to use .
"""
2007-12-17 14:07:51 +03:00
misc . samdb_set_domain_sid ( self , sid )
2007-12-17 10:20:20 +03:00
2007-12-17 14:07:51 +03:00
def attach_schema_from_ldif ( self , pf , df ) :
misc . dsdb_attach_schema_from_ldif_file ( self , pf , df )
2008-01-25 00:08:39 +03:00
def set_invocation_id ( self , invocation_id ) :
""" Set the invocation id for this SamDB handle.
: param invocation_id : GUID of the invocation id .
"""
2008-01-25 03:02:13 +03:00
misc . dsdb_set_ntds_invocation_id ( self , invocation_id )