#!/usr/bin/python # Unix SMB/CIFS implementation. # Copyright (C) Jelmer Vernooij 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 . # """Support for reading Samba 3 data files.""" REGISTRY_VALUE_PREFIX = "SAMBA_REGVAL" REGISTRY_DB_VERSION = 1 import os import tdb class Registry: """Simple read-only support for reading the Samba3 registry.""" def __init__(self, file): self.tdb = tdb.Tdb(file, flags=os.O_RDONLY) def close(self): self.tdb.close() 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)] def subkeys(self, key): data = self.tdb.get("%s\x00" % key) if data is None: return [] import struct (num, ) = struct.unpack("username, /* B */ # &domain_len, &sampass->domain, /* B */ # &nt_username_len, &sampass->nt_username, /* B */ # &fullname_len, &sampass->fullname, /* B */ # &homedir_len, &sampass->homedir, /* B */ # &dir_drive_len, &sampass->dir_drive, /* B */ # &logon_script_len, &sampass->logon_script, /* B */ # &profile_path_len, &sampass->profile_path, /* B */ # &acct_desc_len, &sampass->acct_desc, /* B */ # &workstations_len, &sampass->workstations, /* B */ # &unknown_str_len, &sampass->unknown_str, /* B */ # &munged_dial_len, &sampass->munged_dial, /* B */ # &sampass->user_rid, /* d */ # &sampass->group_rid, /* d */ # &lm_pw_len, sampass->lm_pw.hash, /* B */ # &nt_pw_len, sampass->nt_pw.hash, /* B */ # &sampass->acct_ctrl, /* w */ # &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */ # &sampass->logon_divs, /* w */ # &sampass->hours_len, /* d */ # &hourslen, &sampass->hours, /* B */ # &sampass->bad_password_count, /* w */ # &sampass->logon_count, /* w */ # &sampass->unknown_6); /* d */ # return user def close(self): self.tdb.close() def shellsplit(text): """Very simple shell-like line splitting. :param text: Text to split. :return: List with parts of the line as strings. """ ret = list() inquotes = False current = "" for c in text: if c == "\"": inquotes = not inquotes elif c in ("\t", "\n", " ") and not inquotes: ret.append(current) current = "" else: current += c if current != "": ret.append(current) return ret class WinsDatabase: def __init__(self, file): self.entries = {} f = open(file, 'r') assert f.readline().rstrip("\n") == "VERSION 1 0" for l in f.readlines(): if l[0] == "#": # skip comments continue entries = shellsplit(l.rstrip("\n")) name = entries[0] ttl = int(entries[1]) i = 2 ips = [] while "." in entries[i]: ips.append(entries[i]) i+=1 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 __getitem__(self, name): return self.entries[name] def __len__(self): return len(self.entries) def __iter__(self): return iter(self.entries) def items(self): return self.entries.items() def close(self): # for consistency pass class Samba3: def __init__(self, libdir, smbconfpath): self.smbconfpath = smbconfpath self.libdir = libdir import param self.lp = param.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 = str(lp.get("passdb backend")).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(self.libdir_path("account_policy.tdb")) def get_registry(self): return Registry(self.libdir_path("registry.tdb")) def get_secrets_db(self): return SecretsDatabase(self.libdir_path("secrets.tdb")) def get_shareinfo_db(self): return ShareInfoDatabase(self.libdir_path("share_info.tdb")) def get_idmap_db(self): return IdmapDatabase(self.libdir_path("winbindd_idmap.tdb")) def get_wins_db(self): 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(self.libdir_path("group_mapping.tdb"))