def test_tdb_copy(self): src_ldb_file = os.path.join(self.tempdir, "source.ldb") dst_ldb_file = os.path.join(self.tempdir, "destination.ldb") # Create LDB source file with some content src_ldb = Ldb(src_ldb_file) src_ldb.add({"dn": "f=dc", "b": "bla"}) # Copy source file to destination file and check return status self.assertIsNone(tdb_copy(src_ldb_file, dst_ldb_file)) # Load copied file as LDB object dst_ldb = Ldb(dst_ldb_file) # Copmare contents of files self.assertEqual( src_ldb.searchone(basedn=ldb.Dn(src_ldb, "f=dc"), attribute="b"), dst_ldb.searchone(basedn=ldb.Dn(dst_ldb, "f=dc"), attribute="b") ) # Clean up del src_ldb del dst_ldb os.unlink(src_ldb_file) os.unlink(dst_ldb_file)
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 test_tdb_copy(self): src_ldb_file = os.path.join(self.tempdir, "source.ldb") dst_ldb_file = os.path.join(self.tempdir, "destination.ldb") # Create LDB source file with some content src_ldb = Ldb(src_ldb_file) src_ldb.add({"dn": "f=dc", "b": "bla"}) # Copy source file to destination file and check return status self.assertIsNone(tdb_copy(src_ldb_file, dst_ldb_file)) # Load copied file as LDB object dst_ldb = Ldb(dst_ldb_file) # Copmare contents of files self.assertEqual( src_ldb.searchone(basedn=ldb.Dn(src_ldb, "f=dc"), attribute="b"), dst_ldb.searchone(basedn=ldb.Dn(dst_ldb, "f=dc"), attribute="b")) # Clean up del src_ldb del dst_ldb os.unlink(src_ldb_file) os.unlink(dst_ldb_file)
def create_samdb_copy(samdb, logger, paths, names, domainsid, domainguid): """Create a copy of samdb and give write permissions to named for dns partitions """ private_dir = paths.private_dir samldb_dir = os.path.join(private_dir, "sam.ldb.d") dns_dir = os.path.dirname(paths.dns) dns_samldb_dir = os.path.join(dns_dir, "sam.ldb.d") # Find the partitions and corresponding filenames partfile = {} res = samdb.search(base="@PARTITION", scope=ldb.SCOPE_BASE, attrs=["partition"]) for tmp in res[0]["partition"]: (nc, fname) = tmp.split(':') partfile[nc.upper()] = fname # Create empty domain partition domaindn = names.domaindn.upper() domainpart_file = os.path.join(dns_dir, partfile[domaindn]) try: os.mkdir(dns_samldb_dir) file(domainpart_file, 'w').close() # Fill the basedn and @OPTION records in domain partition dom_ldb = samba.Ldb(domainpart_file) domainguid_line = "objectGUID: %s\n-" % domainguid descr = b64encode(get_domain_descriptor(domainsid)) setup_add_ldif(dom_ldb, setup_path("provision_basedn.ldif"), { "DOMAINDN" : names.domaindn, "DOMAINGUID" : domainguid_line, "DOMAINSID" : str(domainsid), "DESCRIPTOR" : descr}) setup_add_ldif(dom_ldb, setup_path("provision_basedn_options.ldif"), None) except: logger.error( "Failed to setup database for BIND, AD based DNS cannot be used") raise del partfile[domaindn] # Link dns partitions and metadata domainzonedn = "DC=DOMAINDNSZONES,%s" % names.domaindn.upper() forestzonedn = "DC=FORESTDNSZONES,%s" % names.rootdn.upper() domainzone_file = partfile[domainzonedn] forestzone_file = partfile[forestzonedn] metadata_file = "metadata.tdb" try: os.link(os.path.join(samldb_dir, metadata_file), os.path.join(dns_samldb_dir, metadata_file)) os.link(os.path.join(private_dir, domainzone_file), os.path.join(dns_dir, domainzone_file)) os.link(os.path.join(private_dir, forestzone_file), os.path.join(dns_dir, forestzone_file)) except OSError: logger.error( "Failed to setup database for BIND, AD based DNS cannot be used") raise del partfile[domainzonedn] del partfile[forestzonedn] # Copy root, config, schema partitions (and any other if any) # Since samdb is open in the current process, copy them in a child process try: tdb_copy(os.path.join(private_dir, "sam.ldb"), os.path.join(dns_dir, "sam.ldb")) for nc in partfile: pfile = partfile[nc] tdb_copy(os.path.join(private_dir, pfile), os.path.join(dns_dir, pfile)) except: logger.error( "Failed to setup database for BIND, AD based DNS cannot be used") raise # Give bind read/write permissions dns partitions if paths.bind_gid is not None: try: os.chown(samldb_dir, -1, paths.bind_gid) os.chmod(samldb_dir, 0750) for dirname, dirs, files in os.walk(dns_dir): for d in dirs: dpath = os.path.join(dirname, d) os.chown(dpath, -1, paths.bind_gid) os.chmod(dpath, 0770) for f in files: if f.endswith('.ldb') or f.endswith('.tdb'): fpath = os.path.join(dirname, f) os.chown(fpath, -1, paths.bind_gid) os.chmod(fpath, 0660) except OSError: if not os.environ.has_key('SAMBA_SELFTEST'): logger.error( "Failed to set permissions to sam.ldb* files, fix manually") else: if not os.environ.has_key('SAMBA_SELFTEST'): logger.warning("""Unable to find group id for BIND, set permissions to sam.ldb* files manually""")
def create_samdb_copy(samdb, logger, paths, names, domainsid, domainguid): """Create a copy of samdb and give write permissions to named for dns partitions """ private_dir = paths.private_dir samldb_dir = os.path.join(private_dir, "sam.ldb.d") dns_dir = os.path.dirname(paths.dns) dns_samldb_dir = os.path.join(dns_dir, "sam.ldb.d") # Find the partitions and corresponding filenames partfile = {} res = samdb.search(base="@PARTITION", scope=ldb.SCOPE_BASE, attrs=["partition"]) for tmp in res[0]["partition"]: (nc, fname) = tmp.split(':') partfile[nc.upper()] = fname # Create empty domain partition domaindn = names.domaindn.upper() domainpart_file = os.path.join(dns_dir, partfile[domaindn]) try: os.mkdir(dns_samldb_dir) file(domainpart_file, 'w').close() # Fill the basedn and @OPTION records in domain partition dom_ldb = samba.Ldb(domainpart_file) domainguid_line = "objectGUID: %s\n-" % domainguid descr = b64encode(get_domain_descriptor(domainsid)) setup_add_ldif( dom_ldb, setup_path("provision_basedn.ldif"), { "DOMAINDN": names.domaindn, "DOMAINGUID": domainguid_line, "DOMAINSID": str(domainsid), "DESCRIPTOR": descr }) setup_add_ldif(dom_ldb, setup_path("provision_basedn_options.ldif"), None) except: logger.error( "Failed to setup database for BIND, AD based DNS cannot be used") raise # This line is critical to the security of the whole scheme. # We assume there is no secret data in the (to be left out of # date and essentially read-only) config, schema and metadata partitions. # # Only the stub of the domain partition is created above. # # That way, things like the krbtgt key do not leak. del partfile[domaindn] # Link dns partitions and metadata domainzonedn = "DC=DOMAINDNSZONES,%s" % names.domaindn.upper() forestzonedn = "DC=FORESTDNSZONES,%s" % names.rootdn.upper() domainzone_file = partfile[domainzonedn] forestzone_file = partfile.get(forestzonedn) metadata_file = "metadata.tdb" try: os.link(os.path.join(samldb_dir, metadata_file), os.path.join(dns_samldb_dir, metadata_file)) os.link(os.path.join(private_dir, domainzone_file), os.path.join(dns_dir, domainzone_file)) if forestzone_file: os.link(os.path.join(private_dir, forestzone_file), os.path.join(dns_dir, forestzone_file)) except OSError: logger.error( "Failed to setup database for BIND, AD based DNS cannot be used") raise del partfile[domainzonedn] if forestzone_file: del partfile[forestzonedn] # Copy root, config, schema partitions (and any other if any) # Since samdb is open in the current process, copy them in a child process try: tdb_copy(os.path.join(private_dir, "sam.ldb"), os.path.join(dns_dir, "sam.ldb")) for nc in partfile: pfile = partfile[nc] tdb_copy(os.path.join(private_dir, pfile), os.path.join(dns_dir, pfile)) except: logger.error( "Failed to setup database for BIND, AD based DNS cannot be used") raise # Give bind read/write permissions dns partitions if paths.bind_gid is not None: try: os.chown(samldb_dir, -1, paths.bind_gid) os.chmod(samldb_dir, 0750) for dirname, dirs, files in os.walk(dns_dir): for d in dirs: dpath = os.path.join(dirname, d) os.chown(dpath, -1, paths.bind_gid) os.chmod(dpath, 0770) for f in files: if f.endswith('.ldb') or f.endswith('.tdb'): fpath = os.path.join(dirname, f) os.chown(fpath, -1, paths.bind_gid) os.chmod(fpath, 0660) except OSError: if not os.environ.has_key('SAMBA_SELFTEST'): logger.error( "Failed to set permissions to sam.ldb* files, fix manually" ) else: if not os.environ.has_key('SAMBA_SELFTEST'): logger.warning("""Unable to find group id for BIND, set permissions to sam.ldb* files manually""")
def create_samdb_copy(samdb, logger, paths, names, domainsid, domainguid): """Create a copy of samdb and give write permissions to named for dns partitions """ private_dir = paths.private_dir samldb_dir = os.path.join(private_dir, "sam.ldb.d") dns_dir = os.path.dirname(paths.dns) dns_samldb_dir = os.path.join(dns_dir, "sam.ldb.d") # Find the partitions and corresponding filenames partfile = {} res = samdb.search(base="@PARTITION", scope=ldb.SCOPE_BASE, attrs=["partition", "backendStore"]) for tmp in res[0]["partition"]: (nc, fname) = tmp.split(':') partfile[nc.upper()] = fname backend_store = get_default_backend_store() if "backendStore" in res[0]: backend_store = res[0]["backendStore"][0] # Create empty domain partition domaindn = names.domaindn.upper() domainpart_file = os.path.join(dns_dir, partfile[domaindn]) try: os.mkdir(dns_samldb_dir) open(domainpart_file, 'w').close() # Fill the basedn and @OPTION records in domain partition dom_url = "%s://%s" % (backend_store, domainpart_file) dom_ldb = samba.Ldb(dom_url) # We need the dummy main-domain DB to have the correct @INDEXLIST index_res = samdb.search(base="@INDEXLIST", scope=ldb.SCOPE_BASE) dom_ldb.add(index_res[0]) domainguid_line = "objectGUID: %s\n-" % domainguid descr = b64encode(get_domain_descriptor(domainsid)).decode('utf8') setup_add_ldif(dom_ldb, setup_path("provision_basedn.ldif"), { "DOMAINDN" : names.domaindn, "DOMAINGUID" : domainguid_line, "DOMAINSID" : str(domainsid), "DESCRIPTOR" : descr}) setup_add_ldif(dom_ldb, setup_path("provision_basedn_options.ldif"), None) except: logger.error( "Failed to setup database for BIND, AD based DNS cannot be used") raise # This line is critical to the security of the whole scheme. # We assume there is no secret data in the (to be left out of # date and essentially read-only) config, schema and metadata partitions. # # Only the stub of the domain partition is created above. # # That way, things like the krbtgt key do not leak. del partfile[domaindn] # Link dns partitions and metadata domainzonedn = "DC=DOMAINDNSZONES,%s" % names.domaindn.upper() forestzonedn = "DC=FORESTDNSZONES,%s" % names.rootdn.upper() domainzone_file = partfile[domainzonedn] forestzone_file = partfile.get(forestzonedn) metadata_file = "metadata.tdb" try: os.link(os.path.join(samldb_dir, metadata_file), os.path.join(dns_samldb_dir, metadata_file)) os.link(os.path.join(private_dir, domainzone_file), os.path.join(dns_dir, domainzone_file)) if forestzone_file: os.link(os.path.join(private_dir, forestzone_file), os.path.join(dns_dir, forestzone_file)) except OSError: logger.error( "Failed to setup database for BIND, AD based DNS cannot be used") raise del partfile[domainzonedn] if forestzone_file: del partfile[forestzonedn] # Copy root, config, schema partitions (and any other if any) # Since samdb is open in the current process, copy them in a child process try: tdb_copy(os.path.join(private_dir, "sam.ldb"), os.path.join(dns_dir, "sam.ldb")) for nc in partfile: pfile = partfile[nc] if backend_store == "mdb": mdb_copy(os.path.join(private_dir, pfile), os.path.join(dns_dir, pfile)) else: tdb_copy(os.path.join(private_dir, pfile), os.path.join(dns_dir, pfile)) except: logger.error( "Failed to setup database for BIND, AD based DNS cannot be used") raise # Give bind read/write permissions dns partitions if paths.bind_gid is not None: try: for dirname, dirs, files in os.walk(dns_dir): for d in dirs: dpath = os.path.join(dirname, d) os.chown(dpath, -1, paths.bind_gid) os.chmod(dpath, 0o770) for f in files: if f.endswith(('.ldb', '.tdb', 'ldb-lock')): fpath = os.path.join(dirname, f) os.chown(fpath, -1, paths.bind_gid) os.chmod(fpath, 0o660) except OSError: if not os.environ.has_key('SAMBA_SELFTEST'): logger.error( "Failed to set permissions to sam.ldb* files, fix manually") else: if not os.environ.has_key('SAMBA_SELFTEST'): logger.warning("""Unable to find group id for BIND, set permissions to sam.ldb* files manually""")