2007-11-21 15:07:16 +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
#
# Based on the original in EJS:
2007-11-21 15:07:16 +03:00
# Copyright (C) Andrew Tridgell <tridge@samba.org> 2005
#
# 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/>.
#
2008-05-22 19:42:18 +04:00
__docformat__ = " restructuredText "
2007-11-21 15:07:16 +03:00
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
2008-05-22 03:50:38 +04:00
else :
default_ldb_modules_dir = None
2007-12-16 19:17:37 +03:00
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
2008-01-25 05:54:33 +03:00
def searchone ( self , attribute , basedn = None , expression = None ,
2007-12-20 01:27:38 +03:00
scope = ldb . SCOPE_BASE ) :
2007-12-24 04:19:41 +03:00
""" Search for one attribute as a string.
: param basedn : BaseDN for the search .
: param attribute : Name of the attribute
: param expression : Optional search expression .
: param scope : Search scope ( defaults to base ) .
: return : Value of attribute as a string or None if it wasn ' t found.
"""
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
2008-01-25 05:54:33 +03:00
return self . schema_format_value ( attribute , values . pop ( ) )
2007-12-17 10:20:20 +03:00
def erase ( self ) :
2007-12-24 04:19:41 +03:00
""" Erase this ldb, removing all records. """
2007-12-17 10:20:20 +03:00
# delete the specials
for attr in [ " @INDEXLIST " , " @ATTRIBUTES " , " @SUBCLASSES " , " @MODULES " ,
" @OPTIONS " , " @PARTITION " , " @KLUDGEACL " ] :
try :
2008-01-11 18:13:46 +03:00
self . delete ( attr )
2007-12-17 13:12:36 +03:00
except ldb . LdbError , ( LDB_ERR_NO_SUCH_OBJECT , _ ) :
2007-12-17 10:20:20 +03:00
# Ignore missing dn errors
pass
2008-01-11 18:13:46 +03:00
basedn = " "
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 ,
2008-01-11 18:13:46 +03:00
" (&(|(objectclass=*)(distinguishedName=*))(!(distinguishedName=@BASEINFO))) " ,
2008-01-11 18:28:17 +03:00
[ " distinguishedName " ] ) :
2007-12-20 01:27:38 +03:00
try :
self . delete ( msg . dn )
except ldb . LdbError , ( LDB_ERR_NO_SUCH_OBJECT , _ ) :
2008-03-03 05:03:19 +03:00
# Ignore no such object errors
2007-12-20 01:27:38 +03:00
pass
2007-12-17 10:20:20 +03:00
2008-01-11 18:28:17 +03:00
res = self . search ( basedn , ldb . SCOPE_SUBTREE , " (&(|(objectclass=*)(distinguishedName=*))(!(distinguishedName=@BASEINFO))) " , [ " distinguishedName " ] )
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. """
2008-01-11 18:13:46 +03:00
res = self . search ( " " , ldb . SCOPE_BASE , " (objectClass=*) " ,
2007-12-20 01:27:38 +03:00
[ " 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
2008-03-06 23:33:14 +03:00
try :
res2 = self . search ( basedn , ldb . SCOPE_SUBTREE , " (|(objectclass=*)(distinguishedName=*)) " , [ " distinguishedName " ] )
except ldb . LdbError , ( LDB_ERR_NO_SUCH_OBJECT , _ ) :
# Ignore missing dn errors
return
2007-12-20 01:27:38 +03:00
previous_remaining = current_remaining
current_remaining = len ( res2 )
for msg in res2 :
2008-03-03 05:03:19 +03:00
try :
self . delete ( msg . dn )
# Ignore no such object errors
except ldb . LdbError , ( LDB_ERR_NO_SUCH_OBJECT , _ ) :
pass
# Ignore not allowed on non leaf errors
except ldb . LdbError , ( LDB_ERR_NOT_ALLOWED_ON_NON_LEAF , _ ) :
pass
2007-12-20 01:27:38 +03:00
def load_ldif_file_add ( self , ldif_path ) :
""" Load a LDIF file.
: param ldif_path : Path to LDIF file .
"""
2007-12-24 04:19:41 +03:00
self . add_ldif ( open ( ldif_path , ' r ' ) . read ( ) )
2007-12-20 01:27:38 +03:00
2007-12-24 04:19:41 +03:00
def add_ldif ( self , ldif ) :
2007-12-30 03:14:15 +03:00
""" Add data based on a LDIF string.
: param ldif : LDIF text .
"""
2007-12-20 01:27:38 +03:00
for changetype , msg in self . parse_ldif ( ldif ) :
assert changetype == ldb . CHANGETYPE_NONE
self . add ( msg )
2007-12-24 04:19:41 +03:00
def modify_ldif ( self , ldif ) :
2007-12-30 03:14:15 +03:00
""" Modify database based on a LDIF string.
: param ldif : LDIF text .
"""
2008-01-02 10:52:31 +03:00
for changetype , msg in self . parse_ldif ( ldif ) :
2007-12-26 01:36:44 +03:00
self . modify ( msg )
2007-12-24 04:19:41 +03:00
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
2008-01-25 00:18:27 +03:00
def check_all_substituted ( text ) :
""" Make sure that all substitution variables in a string have been replaced.
If not , raise an exception .
: param text : The text to search for substitution variables
"""
if not " $ { " in text :
return
var_start = text . find ( " $ { " )
var_end = text . find ( " } " , var_start )
2008-01-25 03:02:13 +03:00
raise Exception ( " Not all variables substituted: %s " % text [ var_start : var_end + 1 ] )
2008-01-25 00:18:27 +03:00
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)
2008-03-28 00:30:18 +03:00
if len ( name ) > 15 :
2007-12-10 12:29:45 +03:00
return False
return True
2007-12-17 22:03:06 +03:00
version = misc . version