def smb4_restore_tdbfile(tdb_src, tdb_dst): try: db_r = tdb.open(tdb_src, flags=os.O_RDONLY) except Exception as e: print >> sys.stderr, "Unable to open %s: %s" % (tdb_src, e) return False try: db_w = tdb.open(tdb_dst, flags=os.O_RDWR) except Exception as e: print >> sys.stderr, "Unable to open %s: %s" % (tdb_dst, e) return False for key in db_r.iterkeys(): try: db_w.transaction_start() db_w.lock_all() db_w[key] = db_r.get(key) db_w.unlock_all() db_w.transaction_prepare_commit() db_w.transaction_commit() except Exception as e: print >> sys.stderr, "Transaction for key %s failed: %s" % (key, e) db_w.transaction_cancel() db_r.close() db_w.close() return True
def readItem(self, lpath): t = None info = None #self.debug('readItem(%s)...' % (lpath,)) try: fpath = self.fullPath(lpath) st = os.stat(fpath) if stat.S_ISDIR(st[stat.ST_MODE]): t = 'd' except: # it's a file t = 'f' #self.debug('readItem: stat(%s): %s %s' % (fpath, sys.exc_type, sys.exc_value)) pass #self.debug('readItem: type for <%s> is %s' % (lpath, t)) if t == 'f': try: db = tdb.open(self.dirIndexPath(self.parentPath(lpath))) str = db[self.fileName(lpath)] except: #self.debug('readItem: db key for %s not found' % (lpath,)) return None, None info = VFSFileInfo(lpath, str) db.close() elif t == 'd': #print 'readItem: opening %s' % self.dirIndexPath(lpath) try: db = tdb.open(self.dirIndexPath(lpath)) str = db[self.__DirInfoKey] except: return None, None info = VFSDirInfo(lpath, str) db.close() return t, info
def writeItem(self, lpath, data): typ, info = data if info.Type == 'f': db = tdb.open(self.dirIndexPath(self.parentPath(lpath)), True) db[self.fileName(lpath)] = info.serialize() db.sync() db.close() else: # assume 'd' db = tdb.open(self.dirIndexPath(lpath), True) db[self.__DirInfoKey] = info.serialize() db.sync() db.close()
def check_smb_passwd(username, passwd): passdb = tdb.open(smb_passdb) try: user_record = passdb.get("USER_%s\x00" % username.lower()) if not user_record: return False return binascii.a2b_hex(smbpasswd.nthash(passwd)) in user_record finally: passdb.close()
def test_delete_user(): copyfile(DB_ORIGIN, DB_FILE) pdb = PassDB(DB_FILE) del pdb["naota"] pdb.close() db = tdb.open(DB_FILE) assert "USER_naota\x00" not in db assert "RID_000003e8\x00" not in db db.close()
def offline_tdb_copy(self, path): backup_path = path + self.backup_ext try: tdb_copy(path, backup_path, readonly=True) except CalledProcessError as copy_err: # If the copy didn't work, check if it was caused by an EINVAL # error on opening the DB. If so, it's a mutex locked database, # which we can safely ignore. try: tdb.open(path) except Exception as e: if hasattr(e, 'errno') and e.errno == errno.EINVAL: return raise e raise copy_err if not os.path.exists(backup_path): s = "tdbbackup said backup succeeded but {} not found" raise CommandError(s.format(backup_path))
def open_tdb(self): secret_path = f'{SMBPath.PRIVATEDIR.platform()}/secrets.tdb' if os.path.isfile(secret_path): self.tdb = tdb.open(secret_path, self.flags) else: self.tdb = tdb.Tdb(secret_path, 0, tdb.DEFAULT, os.O_CREAT | os.O_RDWR) self.is_open = True
def test_append_user(): copyfile(DB_ORIGIN, DB_FILE) pdb = PassDB(DB_FILE) pdb.append(User("foo")) pdb.close() db = tdb.open(DB_FILE) assert "USER_foo\x00" in db assert db["RID_000003e9\x00"] == "foo\x00" assert db["NEXT_RID\x00"] == "\xea\x03\x00\x00" db.close()
def test_change_password(): copyfile(DB_ORIGIN, DB_FILE) pdb = PassDB(DB_FILE) user = pdb["naota"] user.set_password("hogefuga") pdb["naota"] = user pdb.close() db = tdb.open(DB_FILE) assert unpack_user(db["USER_naota\x00"]).nt_pw == \ nthash("hogefuga").decode("hex") db.close()
def smb4_backup_tdbfile(tdb_src, tdb_dst): try: db_r = tdb.open(tdb_src, flags=os.O_RDONLY) except Exception as e: print >> sys.stderr, "Unable to open %s: %s" % (tdb_src, e) log.error("Unable to open {0}: {1}".format(tdb_src, e)) log_traceback(log=log) return False try: db_w = tdb.open(tdb_dst, flags=os.O_RDWR | os.O_CREAT, mode=0600) except Exception as e: print >> sys.stderr, "Unable to open %s: %s" % (tdb_dst, e) log.error("Unable to open {0}: {1}".format(tdb_dst, e)) log_traceback(log=log) return False for key in db_r.iterkeys(): try: db_w.transaction_start() db_w[key] = db_r.get(key) db_w.transaction_prepare_commit() db_w.transaction_commit() except Exception as e: print >> sys.stderr, "Transaction for key %s failed: %s" % (key, e) log.error("Transaction for key {0} failed: {1}".format(key, e)) log_traceback(log=log) db_w.transaction_cancel() db_r.close() db_w.close() return True
def rmfile(self, lpath): if not self.exists(lpath): return 1, 'Already deleted' if not self.isFile(lpath): return 0, 'Is not a file' info = self.getFileInfo(lpath) try: db = tdb.open(self.dirIndexPath(self.parentPath(lpath))) del db[self.fileName(lpath)] db.sync() db.close() except: return 0, 'Error: %s %s' % (sys.exc_info()[0], sys.exc_info()[1]) vfssrv_global.G_CellIF.delFile(lpath, info.Servers) del self.Cache[lpath] return 1, 'OK'
def validate_groupmap_hwm(self, low_range): """ Middleware forces allocation of GIDs for Users, Groups, and Administrators to be deterministic with the default idmap backend. Bump up the idmap_tdb high-water mark to avoid conflicts with these and remove any mappings that conflict. Winbindd will regenerate the removed ones as-needed. """ must_reload = False try: tdb_handle = tdb.open( f"{SMBPath.STATEDIR.platform()}/winbindd_idmap.tdb") except FileNotFoundError: return must_reload try: group_hwm_bytes = tdb_handle.get(b'GROUP HWM\00') hwm = struct.unpack("<L", group_hwm_bytes)[0] if hwm < low_range + 2: tdb_handle.transaction_start() new_hwm_bytes = struct.pack("<L", group_hwm_bytes) tdb_handle.store(b'GROUP HWM\00', new_hwm_bytes) tdb_handle.transaction_commit() self.middleware.call_sync('idmap.snapshot_samba4_dataset') must_reload = True for key in tdb_handle.keys(): if key[:3] == b'GID' and int( key.decode()[4:-3]) < (low_range + 2): reverse = tdb_handle.get(key) tdb_handle.transaction_start() tdb_handle.delete(key) tdb_handle.delete(reverse) tdb_handle.transaction_commit() if not must_reload: self.middleware.call_sync( 'idmap.snapshot_samba4_dataset') must_reload = True except Exception as e: self.logger.warning("TDB maintenace failed: %s", e) finally: tdb_handle.close() return must_reload
def listDir(self, dir, ptrn='*'): # always returns list of relative paths dir = VFSCanonicPath(dir) lst1 = [] db = tdb.open(self.dirIndexPath(dir)) for fn in self.glob1(dir, ptrn): lpath = dir + '/' + fn typ = self.getType(lpath) info = None if typ == 'f': info = VFSFileInfo(lpath, db[fn]) elif typ == 'd': info = self.getDirInfo(lpath) # remove dir from fn lst1.append((fn, typ, info)) #print 'listDir(%s, %s): lst1(%d): %s' % (dir, ptrn, len(lst1), lst1[:5]) db.close() return lst1
def glob1(self, dirp, ptrn): # returns unsorted list of items in the directory matching the pattern db = tdb.open(self.dirIndexPath(dirp)) lst = list(db.keys()) db.close() #print 'glob1: lst1(%d): %s...' % (len(lst), lst[:5]) lst = list( filter(lambda fn, pt=ptrn, s=self: fn != s.__DirInfoKey and fnmatch .fnmatch(fn, pt), lst)) #print 'glob1: lst2(%d): %s...' % (len(lst), lst[:5]) fullp = self.fullPath(dirp) for fn in glob.glob1(fullp, '*'): if not fn or fn[0] == '.': continue st = os.stat(fullp + '/' + fn) if stat.S_ISDIR(st[stat.ST_MODE]): lst.append(fn) #print 'glob1: lst3(%d): ...%s' % (len(lst), lst[-5:]) return lst
def glob2(self, dirp, ptrn='*'): #print 'glob2: opening %s' % dirp db = tdb.open(self.dirIndexPath(dirp)) files = list( filter(lambda fn, pt=ptrn, s=self: fn != s.__DirInfoKey and fnmatch .fnmatch(fn, pt), list(db.keys()))) lst = [] for fn in files: info = VFSFileInfo(dirp + '/' + fn, db[fn]) lst.append((fn, 'f', info)) db.close() fullp = self.fullPath(dirp) for fn in glob.glob1(fullp, '*'): if not fn or fn[0] == '.': continue st = os.stat(fullp + '/' + fn) if stat.S_ISDIR(st[stat.ST_MODE]): lp = dirp + '/' + fn info = self.getDirInfo(lp) if info != None: lst.append((fn, 'd', info)) return lst
def decrypt_database(args): """Decrypt KCM Databases""" _LOGGER.debug("[*] Opening TDB database...") tdb_db = tdb.open(args.database[0]) _LOGGER.debug("[*] Loading master key...") with open(args.key[0], 'rb') as f: tdb_db_key = f.read() _LOGGER.debug("[*] Printing TDB key values...") lookup_table = list() for key in tdb_db.keys(): if key.decode('ascii', errors='ignore').startswith( ('DN=CN=DEFAULT', 'DN=@BASEINFO', 'DN=CN=CCACHE')) is False: _LOGGER.debug(key) lookup_table.append(key) for key in lookup_table: _LOGGER.debug("[*] Currently processing key: %s", str(key)) raw_key = tdb_db.get(key) secret = raw_key.decode('utf-8', errors='ignore').split('secret')[1].rsplit( '\x00', 1)[0].rsplit('\x00', 1)[1] _LOGGER.debug("Stripped base64 payload: %s", secret) encrypted_secret = base64.b64decode(secret) signature = encrypted_secret[-HMAC_LENGTH:] hmac_input = encrypted_secret[:-HMAC_LENGTH] if hmac.new(tdb_db_key, hmac_input, hashlib.sha256).digest() != signature: _LOGGER.debug("HMAC Authentication Failed") else: _LOGGER.debug("HMAC Authentication Succeeded") iv_bytes = encrypted_secret[:AES_BLOCK_SIZE] encrypted_secret = encrypted_secret[AES_BLOCK_SIZE:] cipher_op = AES.new(tdb_db_key, AES.MODE_CBC, iv_bytes) decrypted_secret = cipher_op.decrypt(encrypted_secret) # This strips out characters that are not needed strip_length = len(decrypted_secret) - 33 b64_kerberos_ticket = decrypted_secret[:strip_length] kerberos_ticket_json = base64.b64decode(b64_kerberos_ticket) print(kerberos_ticket_json.decode('utf-8'))
open(fname, 'w').write(conn.loadfile(rname)) os.utime(fname, (time(), f['mtime'])) if __name__ == '__main__': parse = argparse.ArgumentParser(description='Sysvol replication tool') parse.add_argument('server', help='FQDN of server to replicate sysvol from') args = parse.parse_args() parser = optparse.OptionParser() lp = getopt.SambaOptions(parser).get_loadparm() creds = getopt.CredentialsOptions(parser).get_credentials(lp, fallback_machine=True) conn = smb.SMB(args.server, 'sysvol', lp=lp, creds=creds) gpo_versions = '%s/%s' % (lp.get('path', 'sysvol'), 'versions.tdb') if os.path.isfile(gpo_versions): vers_f = tdb.open(gpo_versions) else: vers_f = tdb.Tdb(gpo_versions, 0, tdb.DEFAULT, os.O_CREAT|os.O_RDWR) gpo_path = win_path_join(lp.get('realm').lower(), 'Policies') gpos = [x['name'] for x in conn.list(gpo_path)] for gpo in gpos: s_gpo_path = win_path_join(gpo_path, gpo) # Check if the version has changed fname = win_path_join(s_gpo_path, 'GPT.INI') data = conn.loadfile(fname) gpt_ini = ConfigParser() gpt_ini.readfp(StringIO(data)) new_vers = gpt_ini.get('General', 'Version') old_vers = vers_f.get(gpo) if (old_vers and old_vers != new_vers) or not old_vers:
def __init__(self, log_file): if os.path.isfile(log_file): self.log = tdb.open(log_file) else: self.log = tdb.Tdb(log_file, 0, tdb.DEFAULT, os.O_CREAT | os.O_RDWR)
# What can be done instead is manipulate the TDB directly # interpreting the format manually # Structure: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/blob/master/src/modules/module-device-restore.c#L363 # The list of tags is found here: # https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/blob/master/src/pulsecore/tagstruct.h # Helper methods: # https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/blob/master/src/pulsecore/tagstruct.c machine_id = open('/etc/machine-id', 'r').read().rstrip() device_volumes_db = os.environ[ 'HOME'] + '/.config/pulse/' + machine_id + '-device-volumes.tdb' default_sink = open(os.environ['HOME'] + '/.config/pulse/' + machine_id + '-default-sink').read().rstrip() default_source = open(os.environ['HOME'] + '/.config/pulse/' + machine_id + '-default-source').read().rstrip() db = tdb.open(device_volumes_db) # Examples: # version 1 - volume not valid (skip rest) # 42 01 30 4e # x = db.get(b'sink:alsa_output.usb-C-Media_Electronics_Inc._Microsoft_LifeChat_LX-3000-00.iec958-stereo:iec958-stereo-output') # bytes(x).hex() # version 1 - volume valid yes - channel map 'm' - volume 'v' - muted valid yes - muted no - number of format 1 # format: tag format 'f' - encoding 01 - proplist 'P' - value # '4201 31 6d020102 760200004a3d00004a3d 31 30 4201 # 66 4201 504e' # mapping of device with port # '4201 31 746d756c74696368616e6e656c2d696e70757400') class per_port_entry(dict):
def __init__(self, name, hash_size=0): self.db = tdb.open(name, hash_size)
def __init__(self, path): write = not os.path.exists(path) or os.access(path, os.W_OK) mode = os.O_RDWR | os.O_CREAT if write else os.O_RDONLY self.db = tdb.open(path, flags=mode)
def __init__(self, filename): self.filename = filename self.context = tdb.open(utils.SmartStr(filename), flags=os.O_CREAT | os.O_RDWR) self.lock = threading.RLock()