"""Support for reading Samba 3 data files."""
+__docformat__ = "restructuredText"
+
REGISTRY_VALUE_PREFIX = "SAMBA_REGVAL"
REGISTRY_DB_VERSION = 1
import os
+import struct
import tdb
-class Registry:
- """Simple read-only support for reading the Samba3 registry."""
+
+def fetch_uint32(tdb, key):
+ try:
+ data = tdb[key]
+ except KeyError:
+ return None
+ assert len(data) == 4
+ return struct.unpack("<L", data)[0]
+
+
+def fetch_int32(tdb, key):
+ try:
+ data = tdb[key]
+ except KeyError:
+ return None
+ assert len(data) == 4
+ return struct.unpack("<l", data)[0]
+
+
+class TdbDatabase(object):
+ """Simple Samba 3 TDB database reader."""
def __init__(self, file):
+ """Open a file.
+
+ :param file: Path of the file to open.
+ """
self.tdb = tdb.Tdb(file, flags=os.O_RDONLY)
+ self._check_version()
+
+ def _check_version(self):
+ pass
def close(self):
+ """Close resources associated with this object."""
self.tdb.close()
+
+class Registry(TdbDatabase):
+ """Simple read-only support for reading the Samba3 registry.
+
+ :note: This object uses the same syntax for registry key paths as
+ Samba 3. This particular format uses forward slashes for key path
+ separators and abbreviations for the predefined key names.
+ e.g.: HKLM/Software/Bar.
+ """
def __len__(self):
"""Return the number of keys."""
return len(self.keys())
def keys(self):
"""Return list with all the keys."""
- return [k.rstrip("\x00") for k in self.tdb.keys() if not k.startswith(REGISTRY_VALUE_PREFIX)]
+ return [k.rstrip("\x00") for k in self.tdb.iterkeys() if not k.startswith(REGISTRY_VALUE_PREFIX)]
def subkeys(self, key):
+ """Retrieve the subkeys for the specified key.
+
+ :param key: Key path.
+ :return: list with key names
+ """
data = self.tdb.get("%s\x00" % key)
if data is None:
return []
- # FIXME: Parse data
- return []
+ (num, ) = struct.unpack("<L", data[0:4])
+ keys = data[4:].split("\0")
+ assert keys[-1] == ""
+ keys.pop()
+ assert len(keys) == num
+ return keys
def values(self, key):
- """Return a dictionary with the values set for a specific key."""
+ """Return a dictionary with the values set for a specific key.
+
+ :param key: Key to retrieve values for.
+ :return: Dictionary with value names as key, tuple with type and
+ data as value."""
data = self.tdb.get("%s/%s\x00" % (REGISTRY_VALUE_PREFIX, key))
if data is None:
return {}
- # FIXME: Parse data
- return {}
+ ret = {}
+ (num, ) = struct.unpack("<L", data[0:4])
+ data = data[4:]
+ for i in range(num):
+ # Value name
+ (name, data) = data.split("\0", 1)
+
+ (type, ) = struct.unpack("<L", data[0:4])
+ data = data[4:]
+ (value_len, ) = struct.unpack("<L", data[0:4])
+ data = data[4:]
+
+ ret[name] = (type, data[:value_len])
+ data = data[value_len:]
+ return ret
-class PolicyDatabase:
+
+class PolicyDatabase(TdbDatabase):
+ """Samba 3 Account Policy database reader."""
def __init__(self, file):
- self.tdb = tdb.Tdb(file, flags=os.O_RDONLY)
- self.min_password_length = self.tdb.fetch_uint32("min password length\x00")
- self.password_history = self.tdb.fetch_uint32("password history\x00")
- self.user_must_logon_to_change_password = self.tdb.fetch_uint32("user must logon to change pasword\x00")
- self.maximum_password_age = self.tdb.fetch_uint32("maximum password age\x00")
- self.minimum_password_age = self.tdb.fetch_uint32("minimum password age\x00")
- self.lockout_duration = self.tdb.fetch_uint32("lockout duration\x00")
- self.reset_count_minutes = self.tdb.fetch_uint32("reset count minutes\x00")
- self.bad_lockout_minutes = self.tdb.fetch_uint32("bad lockout minutes\x00")
- self.disconnect_time = self.tdb.fetch_int32("disconnect time\x00")
- self.refuse_machine_password_change = self.tdb.fetch_uint32("refuse machine password change\x00")
+ """Open a policy database
+
+ :param file: Path to the file to open.
+ """
+ super(PolicyDatabase, self).__init__(file)
+ self.min_password_length = fetch_uint32(self.tdb, "min password length\x00")
+ self.password_history = fetch_uint32(self.tdb, "password history\x00")
+ self.user_must_logon_to_change_password = fetch_uint32(self.tdb, "user must logon to change pasword\x00")
+ self.maximum_password_age = fetch_uint32(self.tdb, "maximum password age\x00")
+ self.minimum_password_age = fetch_uint32(self.tdb, "minimum password age\x00")
+ self.lockout_duration = fetch_uint32(self.tdb, "lockout duration\x00")
+ self.reset_count_minutes = fetch_uint32(self.tdb, "reset count minutes\x00")
+ self.bad_lockout_minutes = fetch_uint32(self.tdb, "bad lockout minutes\x00")
+ self.disconnect_time = fetch_int32(self.tdb, "disconnect time\x00")
+ self.refuse_machine_password_change = fetch_uint32(self.tdb, "refuse machine password change\x00")
# FIXME: Read privileges as well
- def close(self):
- self.tdb.close()
-
GROUPDB_DATABASE_VERSION_V1 = 1 # native byte format.
GROUPDB_DATABASE_VERSION_V2 = 2 # le format.
# hanging of the member as key.
MEMBEROF_PREFIX = "MEMBEROF/"
-class GroupMappingDatabase:
- def __init__(self, file):
- self.tdb = tdb.Tdb(file, flags=os.O_RDONLY)
- assert self.tdb.fetch_int32("INFO/version\x00") in (GROUPDB_DATABASE_VERSION_V1, GROUPDB_DATABASE_VERSION_V2)
+class GroupMappingDatabase(TdbDatabase):
+ """Samba 3 group mapping database reader."""
+ def _check_version(self):
+ assert fetch_int32(self.tdb, "INFO/version\x00") in (GROUPDB_DATABASE_VERSION_V1, GROUPDB_DATABASE_VERSION_V2)
def groupsids(self):
- for k in self.tdb.keys():
+ """Retrieve the SIDs for the groups in this database.
+
+ :return: List with sids as strings.
+ """
+ for k in self.tdb.iterkeys():
if k.startswith(GROUP_PREFIX):
yield k[len(GROUP_PREFIX):].rstrip("\0")
+ def get_group(self, sid):
+ """Retrieve the group mapping information for a particular group.
+
+ :param sid: SID of the group
+ :return: None if the group can not be found, otherwise
+ a tuple with gid, sid_name_use, the NT name and comment.
+ """
+ data = self.tdb.get("%s%s\0" % (GROUP_PREFIX, sid))
+ if data is None:
+ return data
+ (gid, sid_name_use) = struct.unpack("<lL", data[0:8])
+ (nt_name, comment, _) = data[8:].split("\0")
+ return (gid, sid_name_use, nt_name, comment)
+
def aliases(self):
- for k in self.tdb.keys():
+ """Retrieve the aliases in this database."""
+ for k in self.tdb.iterkeys():
if k.startswith(MEMBEROF_PREFIX):
yield k[len(MEMBEROF_PREFIX):].rstrip("\0")
- def close(self):
- self.tdb.close()
-
# High water mark keys
IDMAP_HWM_GROUP = "GROUP HWM\0"
# idmap version determines auto-conversion
IDMAP_VERSION_V2 = 2
-class IdmapDatabase:
- def __init__(self, file):
- self.tdb = tdb.Tdb(file, flags=os.O_RDONLY)
- assert self.tdb.fetch_int32("IDMAP_VERSION\0") == IDMAP_VERSION_V2
+class IdmapDatabase(TdbDatabase):
+ """Samba 3 ID map database reader."""
+ def _check_version(self):
+ assert fetch_int32(self.tdb, "IDMAP_VERSION\0") == IDMAP_VERSION_V2
def uids(self):
- for k in self.tdb.keys():
+ """Retrieve a list of all uids in this database."""
+ for k in self.tdb.iterkeys():
if k.startswith(IDMAP_USER_PREFIX):
yield int(k[len(IDMAP_USER_PREFIX):].rstrip("\0"))
def gids(self):
- for k in self.tdb.keys():
+ """Retrieve a list of all gids in this database."""
+ for k in self.tdb.iterkeys():
if k.startswith(IDMAP_GROUP_PREFIX):
yield int(k[len(IDMAP_GROUP_PREFIX):].rstrip("\0"))
def get_user_sid(self, uid):
+ """Retrieve the SID associated with a particular uid.
+
+ :param uid: UID to retrieve SID for.
+ :return: A SID or None if no mapping was found.
+ """
data = self.tdb.get("%s%d\0" % (IDMAP_USER_PREFIX, uid))
if data is None:
return data
return data.rstrip("\0")
def get_user_hwm(self):
- return self.tdb.fetch_uint32(IDMAP_HWM_USER)
+ """Obtain the user high-water mark."""
+ return fetch_uint32(self.tdb, IDMAP_HWM_USER)
def get_group_hwm(self):
- return self.tdb.fetch_uint32(IDMAP_HWM_GROUP)
-
- def close(self):
- self.tdb.close()
-
+ """Obtain the group high-water mark."""
+ return fetch_uint32(self.tdb, IDMAP_HWM_GROUP)
-class SecretsDatabase:
- def __init__(self, file):
- self.tdb = tdb.Tdb(file, flags=os.O_RDONLY)
+class SecretsDatabase(TdbDatabase):
+ """Samba 3 Secrets database reader."""
def get_auth_password(self):
return self.tdb.get("SECRETS/AUTH_PASSWORD")
def get_auth_user(self):
return self.tdb.get("SECRETS/AUTH_USER")
- def get_dom_guid(self, host):
+ def get_domain_guid(self, host):
return self.tdb.get("SECRETS/DOMGUID/%s" % host)
def ldap_dns(self):
- for k in self.tdb.keys():
+ for k in self.tdb.iterkeys():
if k.startswith("SECRETS/LDAP_BIND_PW/"):
yield k[len("SECRETS/LDAP_BIND_PW/"):].rstrip("\0")
def domains(self):
- for k in self.tdb.keys():
+ """Iterate over domains in this database.
+
+ :return: Iterator over the names of domains in this database.
+ """
+ for k in self.tdb.iterkeys():
if k.startswith("SECRETS/SID/"):
yield k[len("SECRETS/SID/"):].rstrip("\0")
return self.tdb.get("SECRETS/AFS_KEYFILE/%s" % host)
def get_machine_sec_channel_type(self, host):
- return self.tdb.fetch_uint32("SECRETS/MACHINE_SEC_CHANNEL_TYPE/%s" % host)
+ return fetch_uint32(self.tdb, "SECRETS/MACHINE_SEC_CHANNEL_TYPE/%s" % host)
def get_machine_last_change_time(self, host):
- return self.tdb.fetch_uint32("SECRETS/MACHINE_LAST_CHANGE_TIME/%s" % host)
+ return fetch_uint32(self.tdb, "SECRETS/MACHINE_LAST_CHANGE_TIME/%s" % host)
def get_machine_password(self, host):
return self.tdb.get("SECRETS/MACHINE_PASSWORD/%s" % host)
return self.tdb.get("SECRETS/$DOMTRUST.ACC/%s" % host)
def trusted_domains(self):
- for k in self.tdb.keys():
+ for k in self.tdb.iterkeys():
if k.startswith("SECRETS/$DOMTRUST.ACC/"):
yield k[len("SECRETS/$DOMTRUST.ACC/"):].rstrip("\0")
def get_sid(self, host):
return self.tdb.get("SECRETS/SID/%s" % host.upper())
- def close(self):
- self.tdb.close()
-
SHARE_DATABASE_VERSION_V1 = 1
SHARE_DATABASE_VERSION_V2 = 2
-class ShareInfoDatabase:
- def __init__(self, file):
- self.tdb = tdb.Tdb(file, flags=os.O_RDONLY)
- assert self.tdb.fetch_int32("INFO/version") in (SHARE_DATABASE_VERSION_V1, SHARE_DATABASE_VERSION_V2)
+class ShareInfoDatabase(TdbDatabase):
+ """Samba 3 Share Info database reader."""
+ def _check_version(self):
+ assert fetch_int32(self.tdb, "INFO/version\0") in (SHARE_DATABASE_VERSION_V1, SHARE_DATABASE_VERSION_V2)
def get_secdesc(self, name):
+ """Obtain the security descriptor on a particular share.
+
+ :param name: Name of the share
+ """
secdesc = self.tdb.get("SECDESC/%s" % name)
# FIXME: Run ndr_pull_security_descriptor
return secdesc
- def close(self):
- self.tdb.close()
+
+class Shares(object):
+ """Container for share objects."""
+ def __init__(self, lp, shareinfo):
+ self.lp = lp
+ self.shareinfo = shareinfo
+
+ def __len__(self):
+ """Number of shares."""
+ return len(self.lp) - 1
+
+ def __iter__(self):
+ """Iterate over the share names."""
+ return self.lp.__iter__()
+
ACB_DISABLED = 0x00000001
ACB_HOMDIRREQ = 0x00000002
ACB_NO_AUTH_DATA_REQD = 0x00080000
acb_info_mapping = {
- 'N': ACB_PWNOTREQ, # 'N'o password.
+ 'N': ACB_PWNOTREQ, # 'N'o password.
'D': ACB_DISABLED, # 'D'isabled.
- 'H': ACB_HOMDIRREQ, # 'H'omedir required.
- 'T': ACB_TEMPDUP, # 'T'emp account.
- 'U': ACB_NORMAL, # 'U'ser account (normal).
- 'M': ACB_MNS, # 'M'NS logon user account. What is this ?
- 'W': ACB_WSTRUST, # 'W'orkstation account.
- 'S': ACB_SVRTRUST, # 'S'erver account.
- 'L': ACB_AUTOLOCK, # 'L'ocked account.
- 'X': ACB_PWNOEXP, # No 'X'piry on password
- 'I': ACB_DOMTRUST, # 'I'nterdomain trust account.
+ 'H': ACB_HOMDIRREQ, # 'H'omedir required.
+ 'T': ACB_TEMPDUP, # 'T'emp account.
+ 'U': ACB_NORMAL, # 'U'ser account (normal).
+ 'M': ACB_MNS, # 'M'NS logon user account. What is this ?
+ 'W': ACB_WSTRUST, # 'W'orkstation account.
+ 'S': ACB_SVRTRUST, # 'S'erver account.
+ 'L': ACB_AUTOLOCK, # 'L'ocked account.
+ 'X': ACB_PWNOEXP, # No 'X'piry on password
+ 'I': ACB_DOMTRUST, # 'I'nterdomain trust account.
' ': 0
}
def decode_acb(text):
+ """Decode a ACB field.
+
+ :param text: ACB text
+ :return: integer with flags set.
+ """
assert not "[" in text and not "]" in text
ret = 0
for x in text:
return ret
-class SmbpasswdFile:
+class SAMUser(object):
+ """Samba 3 SAM User.
+
+ :note: Unknown or unset fields are set to None.
+ """
+ def __init__(self, name, uid=None, lm_password=None, nt_password=None, acct_ctrl=None,
+ last_change_time=None, nt_username=None, fullname=None, logon_time=None, logoff_time=None,
+ acct_desc=None, group_rid=None, bad_password_count=None, logon_count=None,
+ domain=None, dir_drive=None, munged_dial=None, homedir=None, logon_script=None,
+ profile_path=None, workstations=None, kickoff_time=None, bad_password_time=None,
+ pass_last_set_time=None, pass_can_change_time=None, pass_must_change_time=None,
+ user_rid=None, unknown_6=None, nt_password_history=None,
+ unknown_str=None, hours=None, logon_divs=None):
+ self.username = name
+ self.uid = uid
+ self.lm_password = lm_password
+ self.nt_password = nt_password
+ self.acct_ctrl = acct_ctrl
+ self.pass_last_set_time = last_change_time
+ self.nt_username = nt_username
+ self.fullname = fullname
+ self.logon_time = logon_time
+ self.logoff_time = logoff_time
+ self.acct_desc = acct_desc
+ self.group_rid = group_rid
+ self.bad_password_count = bad_password_count
+ self.logon_count = logon_count
+ self.domain = domain
+ self.dir_drive = dir_drive
+ self.munged_dial = munged_dial
+ self.homedir = homedir
+ self.logon_script = logon_script
+ self.profile_path = profile_path
+ self.workstations = workstations
+ self.kickoff_time = kickoff_time
+ self.bad_password_time = bad_password_time
+ self.pass_can_change_time = pass_can_change_time
+ self.pass_must_change_time = pass_must_change_time
+ self.user_rid = user_rid
+ self.unknown_6 = unknown_6
+ self.nt_password_history = nt_password_history
+ self.unknown_str = unknown_str
+ self.hours = hours
+ self.logon_divs = logon_divs
+
+ def __eq__(self, other):
+ if not isinstance(other, SAMUser):
+ return False
+ return self.__dict__ == other.__dict__
+
+
+class SmbpasswdFile(object):
+ """Samba 3 smbpasswd file reader."""
def __init__(self, file):
self.users = {}
f = open(file, 'r')
acct_ctrl &= ~ACB_NORMAL
acct_ctrl |= ACB_WSTRUST
- self.users[username] = (uid, lm_password, nt_password, acct_ctrl, last_change_time)
+ self.users[username] = SAMUser(username, uid, lm_password, nt_password, acct_ctrl, last_change_time)
f.close()
return self.users[name]
def __iter__(self):
- return iter(self.entries)
+ return iter(self.users)
def close(self): # For consistency
pass
TDBSAM_USER_PREFIX = "USER_"
-class TdbSam:
- def __init__(self, file):
- self.tdb = tdb.Tdb(file, flags=os.O_RDONLY)
- self.version = self.tdb.fetch_uint32("INFO/version") or 0
- assert self.version in (0, 1, 2)
+class LdapSam(object):
+ """Samba 3 LDAP passdb backend reader."""
+ def __init__(self, url):
+ self.ldap_url = url
+
+
+class TdbSam(TdbDatabase):
+ """Samba 3 TDB passdb backend reader."""
+ def _check_version(self):
+ self.version = fetch_uint32(self.tdb, "INFO/version\0") or 0
+ assert self.version in (0, 1, 2, 3)
def usernames(self):
- for k in self.tdb.keys():
+ """Iterate over the usernames in this Tdb database."""
+ for k in self.tdb.iterkeys():
if k.startswith(TDBSAM_USER_PREFIX):
yield k[len(TDBSAM_USER_PREFIX):].rstrip("\0")
- def close(self):
- self.tdb.close()
+ __iter__ = usernames
+
+ def __getitem__(self, name):
+ data = self.tdb["%s%s\0" % (TDBSAM_USER_PREFIX, name)]
+ user = SAMUser(name)
+
+ def unpack_string(data):
+ (length, ) = struct.unpack("<L", data[:4])
+ data = data[4:]
+ if length == 0:
+ return (None, data)
+ return (data[:length].rstrip("\0"), data[length:])
+
+ def unpack_int32(data):
+ (value, ) = struct.unpack("<l", data[:4])
+ return (value, data[4:])
+
+ def unpack_uint32(data):
+ (value, ) = struct.unpack("<L", data[:4])
+ return (value, data[4:])
+
+ def unpack_uint16(data):
+ (value, ) = struct.unpack("<H", data[:2])
+ return (value, data[2:])
+
+ (logon_time, data) = unpack_int32(data)
+ (logoff_time, data) = unpack_int32(data)
+ (kickoff_time, data) = unpack_int32(data)
+
+ if self.version > 0:
+ (bad_password_time, data) = unpack_int32(data)
+ if bad_password_time != 0:
+ user.bad_password_time = bad_password_time
+ (pass_last_set_time, data) = unpack_int32(data)
+ (pass_can_change_time, data) = unpack_int32(data)
+ (pass_must_change_time, data) = unpack_int32(data)
+
+ if logon_time != 0:
+ user.logon_time = logon_time
+ user.logoff_time = logoff_time
+ user.kickoff_time = kickoff_time
+ if pass_last_set_time != 0:
+ user.pass_last_set_time = pass_last_set_time
+ user.pass_can_change_time = pass_can_change_time
+
+ (user.username, data) = unpack_string(data)
+ (user.domain, data) = unpack_string(data)
+ (user.nt_username, data) = unpack_string(data)
+ (user.fullname, data) = unpack_string(data)
+ (user.homedir, data) = unpack_string(data)
+ (user.dir_drive, data) = unpack_string(data)
+ (user.logon_script, data) = unpack_string(data)
+ (user.profile_path, data) = unpack_string(data)
+ (user.acct_desc, data) = unpack_string(data)
+ (user.workstations, data) = unpack_string(data)
+ (user.unknown_str, data) = unpack_string(data)
+ (user.munged_dial, data) = unpack_string(data)
+
+ (user.user_rid, data) = unpack_int32(data)
+ (user.group_rid, data) = unpack_int32(data)
+
+ (user.lm_password, data) = unpack_string(data)
+ (user.nt_password, data) = unpack_string(data)
+
+ if self.version > 1:
+ (user.nt_password_history, data) = unpack_string(data)
+
+ (user.acct_ctrl, data) = unpack_uint16(data)
+ (_, data) = unpack_uint32(data) # remove_me field
+ (user.logon_divs, data) = unpack_uint16(data)
+ (hours, data) = unpack_string(data)
+ user.hours = []
+ for entry in hours:
+ for i in range(8):
+ user.hours.append(ord(entry) & (2 ** i) == (2 ** i))
+ # FIXME
+ #(user.bad_password_count, data) = unpack_uint16(data)
+ #(user.logon_count, data) = unpack_uint16(data)
+ #(user.unknown_6, data) = unpack_uint32(data)
+ assert len(data) == 0
+ return user
def shellsplit(text):
return ret
-class WinsDatabase:
+class WinsDatabase(object):
+ """Samba 3 WINS database reader."""
def __init__(self, file):
self.entries = {}
f = open(file, 'r')
while "." in entries[i]:
ips.append(entries[i])
i+=1
- nb_flags = entries[i]
+ nb_flags = int(entries[i][:-1], 16)
assert not name in self.entries, "Name %s exists twice" % name
self.entries[name] = (ttl, ips, nb_flags)
f.close()
def __iter__(self):
return iter(self.entries)
+ def items(self):
+ """Return the entries in this WINS database."""
+ return self.entries.items()
+
def close(self): # for consistency
pass
-class Samba3:
+
+class ParamFile(object):
+ """Simple smb.conf-compatible file parser
+
+ Does not use a parameter table, unlike the "normal".
+ """
+
+ def __init__(self, sections=None):
+ self._sections = sections or {}
+
+ def _sanitize_name(self, name):
+ return name.strip().lower().replace(" ","")
+
+ def __repr__(self):
+ return "ParamFile(%r)" % self._sections
+
+ def read(self, filename):
+ """Read a file.
+
+ :param filename: Path to the file
+ """
+ section = None
+ for i, l in enumerate(open(filename, 'r').xreadlines()):
+ l = l.strip()
+ if not l or l[0] == '#' or l[0] == ';':
+ continue
+ if l[0] == "[" and l[-1] == "]":
+ section = self._sanitize_name(l[1:-1])
+ self._sections.setdefault(section, {})
+ elif "=" in l:
+ (k, v) = l.split("=", 1)
+ self._sections[section][self._sanitize_name(k)] = v
+ else:
+ raise Exception("Unable to parser line %d: %r" % (i+1,l))
+
+ def get(self, param, section=None):
+ """Return the value of a parameter.
+
+ :param param: Parameter name
+ :param section: Section name, defaults to "global"
+ :return: parameter value as string if found, None otherwise.
+ """
+ if section is None:
+ section = "global"
+ section = self._sanitize_name(section)
+ if not section in self._sections:
+ return None
+ param = self._sanitize_name(param)
+ if not param in self._sections[section]:
+ return None
+ return self._sections[section][param].strip()
+
+ def __getitem__(self, section):
+ return self._sections[section]
+
+ def get_section(self, section):
+ return self._sections.get(section)
+
+ def add_section(self, section):
+ self._sections[self._sanitize_name(section)] = {}
+
+ def set_string(self, name, value):
+ self._sections["global"][name] = value
+
+ def get_string(self, name):
+ return self._sections["global"].get(name)
+
+
+class Samba3(object):
+ """Samba 3 configuration and state data reader."""
def __init__(self, libdir, smbconfpath):
+ """Open the configuration and data for a Samba 3 installation.
+
+ :param libdir: Library directory
+ :param smbconfpath: Path to the smb.conf file.
+ """
self.smbconfpath = smbconfpath
self.libdir = libdir
+ self.lp = ParamFile()
+ self.lp.read(self.smbconfpath)
+
+ def libdir_path(self, path):
+ if path[0] == "/" or path[0] == ".":
+ return path
+ return os.path.join(self.libdir, path)
+
+ def get_conf(self):
+ return self.lp
+
+ def get_sam_db(self):
+ lp = self.get_conf()
+ backends = (lp.get("passdb backend") or "").split(" ")
+ if ":" in backends[0]:
+ (name, location) = backends[0].split(":", 2)
+ else:
+ name = backends[0]
+ location = None
+ if name == "smbpasswd":
+ return SmbpasswdFile(self.libdir_path(location or "smbpasswd"))
+ elif name == "tdbsam":
+ return TdbSam(self.libdir_path(location or "passdb.tdb"))
+ elif name == "ldapsam":
+ if location is not None:
+ return LdapSam("ldap:%s" % location)
+ return LdapSam(lp.get("ldap server"))
+ else:
+ raise NotImplementedError("unsupported passdb backend %s" % backends[0])
def get_policy_db(self):
- return PolicyDatabase(os.path.join(self.libdir, "account_policy.tdb"))
+ return PolicyDatabase(self.libdir_path("account_policy.tdb"))
def get_registry(self):
- return Registry(os.path.join(self.libdir, "registry.tdb"))
+ return Registry(self.libdir_path("registry.tdb"))
def get_secrets_db(self):
- return SecretsDatabase(os.path.join(self.libdir, "secrets.tdb"))
+ return SecretsDatabase(self.libdir_path("secrets.tdb"))
- def get_shares_db(self):
- return ShareInfoDatabase(os.path.join(self.libdir, "share_info.tdb"))
+ def get_shareinfo_db(self):
+ return ShareInfoDatabase(self.libdir_path("share_info.tdb"))
def get_idmap_db(self):
- return IdmapDatabase(os.path.join(self.libdir, "winbindd_idmap.tdb"))
+ return IdmapDatabase(self.libdir_path("winbindd_idmap.tdb"))
def get_wins_db(self):
- return WinsDatabase(os.path.join(self.libdir, "wins.dat"))
+ return WinsDatabase(self.libdir_path("wins.dat"))
+
+ def get_shares(self):
+ return Shares(self.get_conf(), self.get_shareinfo_db())
def get_groupmapping_db(self):
- return GroupMappingDatabase(os.path.join(self.libdir, "group_mapping.tdb"))
+ return GroupMappingDatabase(self.libdir_path("group_mapping.tdb"))