2007-11-21 15:07:16 +03:00
#!/usr/bin/python
# Unix SMB/CIFS implementation.
# Copyright (C) Andrew Tridgell <tridge@samba.org> 2005
# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
#
# 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/>.
#
import os
2007-12-16 17:33:58 +03:00
def _in_source_tree ( ) :
2007-12-16 19:17:37 +03:00
""" Check whether the script is being run from the source dir. """
2007-12-16 17:50:02 +03:00
return os . path . exists ( " %s /../../../samba4-skip " % os . path . dirname ( __file__ ) )
2007-12-16 17:33:58 +03:00
2007-12-16 19:17:37 +03:00
2007-12-16 17:33:58 +03:00
# When running, in-tree, make sure bin/python is in the PYTHONPATH
if _in_source_tree ( ) :
import sys
2007-12-16 19:17:37 +03:00
srcdir = " %s /../../.. " % os . path . dirname ( __file__ )
sys . path . append ( " %s /bin/python " % srcdir )
default_ldb_modules_dir = " %s /bin/modules/ldb " % srcdir
2007-12-16 17:33:58 +03:00
2007-12-16 17:50:02 +03:00
import ldb
2007-12-17 13:12:36 +03:00
import credentials
import misc
2007-12-17 10:20:20 +03:00
class Ldb ( ldb . Ldb ) :
""" Simple Samba-specific LDB subclass that takes care
of setting up the modules dir , credentials pointers , etc .
Please note that this is intended to be for all Samba LDB files ,
not necessarily the Sam database . For Sam - specific helper
functions see samdb . py .
2007-11-21 15:07:16 +03:00
"""
2007-12-17 13:12:36 +03:00
def __init__ ( self , url = None , session_info = None , credentials = None ,
modules_dir = None , lp = None ) :
2007-12-17 10:20:20 +03:00
""" Open a Samba Ldb file.
2007-12-17 13:12:36 +03:00
: param url : Optional LDB URL to open
2007-12-17 10:20:20 +03:00
: param session_info : Optional session information
: param credentials : Optional credentials , defaults to anonymous .
2007-12-17 13:12:36 +03:00
: param modules_dir : Modules directory , if not the default .
2007-12-17 10:20:20 +03:00
: param lp : Loadparm object , optional .
This is different from a regular Ldb file in that the Samba - specific
modules - dir is used by default and that credentials and session_info
can be passed through ( required by some modules ) .
"""
2007-12-17 13:12:36 +03:00
super ( Ldb , self ) . __init__ ( )
2007-12-17 10:20:20 +03:00
if modules_dir is not None :
2007-12-17 13:12:36 +03:00
self . set_modules_dir ( modules_dir )
elif default_ldb_modules_dir is not None :
self . set_modules_dir ( default_ldb_modules_dir )
2007-12-17 10:20:20 +03:00
if credentials is not None :
2007-12-17 13:12:36 +03:00
self . set_credentials ( self , credentials )
2007-12-17 10:20:20 +03:00
if session_info is not None :
2007-12-17 13:12:36 +03:00
self . set_session_info ( self , session_info )
2007-12-20 17:53:56 +03:00
assert misc . ldb_register_samba_handlers ( self ) == 0
2007-12-17 10:20:20 +03:00
if lp is not None :
2007-12-17 13:12:36 +03:00
self . set_loadparm ( self , lp )
2007-12-18 04:21:14 +03:00
def msg ( l , text ) :
print text
2007-12-18 19:21:13 +03:00
#self.set_debug(msg)
2007-12-18 04:21:14 +03:00
2007-12-18 04:21:28 +03:00
if url is not None :
self . connect ( url )
2007-12-17 13:12:36 +03:00
set_credentials = misc . ldb_set_credentials
set_session_info = misc . ldb_set_session_info
set_loadparm = misc . ldb_set_loadparm
2007-12-17 10:20:20 +03:00
2007-12-20 01:27:38 +03:00
def searchone ( self , basedn , attribute , expression = None ,
scope = ldb . SCOPE_BASE ) :
2007-12-17 10:20:20 +03:00
""" Search for one attribute as a string. """
2007-12-18 19:21:13 +03:00
res = self . search ( basedn , scope , expression , [ attribute ] )
2007-12-17 10:20:20 +03:00
if len ( res ) != 1 or res [ 0 ] [ attribute ] is None :
return None
2007-12-20 01:27:31 +03:00
values = set ( res [ 0 ] [ attribute ] )
assert len ( values ) == 1
return values . pop ( )
2007-12-17 10:20:20 +03:00
def erase ( self ) :
""" Erase an ldb, removing all records. """
# delete the specials
for attr in [ " @INDEXLIST " , " @ATTRIBUTES " , " @SUBCLASSES " , " @MODULES " ,
" @OPTIONS " , " @PARTITION " , " @KLUDGEACL " ] :
try :
2007-12-17 13:12:36 +03:00
self . delete ( ldb . Dn ( self , attr ) )
except ldb . LdbError , ( LDB_ERR_NO_SUCH_OBJECT , _ ) :
2007-12-17 10:20:20 +03:00
# Ignore missing dn errors
pass
2007-12-17 13:12:36 +03:00
basedn = ldb . Dn ( self , " " )
2007-12-17 10:20:20 +03:00
# and the rest
2007-12-17 13:12:36 +03:00
for msg in self . search ( basedn , ldb . SCOPE_SUBTREE ,
2007-12-17 10:20:20 +03:00
" (&(|(objectclass=*)(dn=*))(!(dn=@BASEINFO))) " ,
[ " dn " ] ) :
2007-12-20 01:27:38 +03:00
try :
self . delete ( msg . dn )
except ldb . LdbError , ( LDB_ERR_NO_SUCH_OBJECT , _ ) :
# Ignor eno such object errors
pass
2007-12-17 10:20:20 +03:00
2007-12-17 13:12:36 +03:00
res = self . search ( basedn , ldb . SCOPE_SUBTREE , " (&(|(objectclass=*)(dn=*))(!(dn=@BASEINFO))) " , [ " dn " ] )
2007-12-17 10:20:20 +03:00
assert len ( res ) == 0
2007-11-21 15:07:16 +03:00
2007-12-20 01:27:38 +03:00
def erase_partitions ( self ) :
""" Erase an ldb, removing all records. """
res = self . search ( ldb . Dn ( self , " " ) , ldb . SCOPE_BASE , " (objectClass=*) " ,
[ " namingContexts " ] )
assert len ( res ) == 1
if not " namingContexts " in res [ 0 ] :
return
for basedn in res [ 0 ] [ " namingContexts " ] :
previous_remaining = 1
current_remaining = 0
k = 0
while + + k < 10 and ( previous_remaining != current_remaining ) :
# and the rest
res2 = self . search ( ldb . Dn ( self , basedn ) , ldb . SCOPE_SUBTREE , " (|(objectclass=*)(dn=*)) " , [ " dn " ] )
previous_remaining = current_remaining
current_remaining = len ( res2 )
for msg in res2 :
self . delete ( msg . dn )
def load_ldif_file_add ( self , ldif_path ) :
""" Load a LDIF file.
: param ldif_path : Path to LDIF file .
"""
self . load_ldif_add ( open ( ldif_path , ' r ' ) . read ( ) )
def load_ldif_add ( self , ldif ) :
for changetype , msg in self . parse_ldif ( ldif ) :
assert changetype == ldb . CHANGETYPE_NONE
self . add ( msg )
2007-11-21 15:07:16 +03:00
def substitute_var ( text , values ) :
""" substitute strings of the form $ {NAME} in str, replacing
with substitutions from subobj .
: param text : Text in which to subsitute .
: param values : Dictionary with keys and values .
"""
for ( name , value ) in values . items ( ) :
2007-12-18 19:21:13 +03:00
assert isinstance ( name , str ) , " %r is not a string " % name
assert isinstance ( value , str ) , " Value %r for %s is not a string " % ( value , name )
2007-11-21 15:07:16 +03:00
text = text . replace ( " $ { %s } " % name , value )
return text
2007-12-10 12:29:45 +03:00
def valid_netbios_name ( name ) :
""" Check whether a name is valid as a NetBIOS name. """
# FIXME: There are probably more constraints here.
# crh has a paragraph on this in his book (1.4.1.1)
if len ( name ) > 13 :
return False
return True
2007-12-17 22:03:06 +03:00
version = misc . version