def setup_dns_partitions(samdb, domainsid, domaindn, forestdn, configdn, serverdn, fill_level): domainzone_dn = "DC=DomainDnsZones,%s" % domaindn forestzone_dn = "DC=ForestDnsZones,%s" % forestdn descriptor = get_dns_partition_descriptor(domainsid) setup_add_ldif(samdb, setup_path("provision_dnszones_partitions.ldif"), { "ZONE_DN": domainzone_dn, "SECDESC" : b64encode(descriptor) }) if fill_level != FILL_SUBDOMAIN: setup_add_ldif(samdb, setup_path("provision_dnszones_partitions.ldif"), { "ZONE_DN": forestzone_dn, "SECDESC" : b64encode(descriptor) }) domainzone_guid = get_domainguid(samdb, domainzone_dn) forestzone_guid = get_domainguid(samdb, forestzone_dn) domainzone_guid = str(uuid.uuid4()) forestzone_guid = str(uuid.uuid4()) domainzone_dns = ldb.Dn(samdb, domainzone_dn).canonical_ex_str().strip() forestzone_dns = ldb.Dn(samdb, forestzone_dn).canonical_ex_str().strip() protected1_desc = get_domain_delete_protected1_descriptor(domainsid) protected2_desc = get_domain_delete_protected2_descriptor(domainsid) setup_add_ldif(samdb, setup_path("provision_dnszones_add.ldif"), { "ZONE_DN": domainzone_dn, "ZONE_GUID": domainzone_guid, "ZONE_DNS": domainzone_dns, "CONFIGDN": configdn, "SERVERDN": serverdn, "LOSTANDFOUND_DESCRIPTOR": b64encode(protected2_desc), "INFRASTRUCTURE_DESCRIPTOR": b64encode(protected1_desc), }) setup_modify_ldif(samdb, setup_path("provision_dnszones_modify.ldif"), { "CONFIGDN": configdn, "SERVERDN": serverdn, "ZONE_DN": domainzone_dn, }) if fill_level != FILL_SUBDOMAIN: setup_add_ldif(samdb, setup_path("provision_dnszones_add.ldif"), { "ZONE_DN": forestzone_dn, "ZONE_GUID": forestzone_guid, "ZONE_DNS": forestzone_dns, "CONFIGDN": configdn, "SERVERDN": serverdn, "LOSTANDFOUND_DESCRIPTOR": b64encode(protected2_desc), "INFRASTRUCTURE_DESCRIPTOR": b64encode(protected1_desc), }) setup_modify_ldif(samdb, setup_path("provision_dnszones_modify.ldif"), { "CONFIGDN": configdn, "SERVERDN": serverdn, "ZONE_DN": forestzone_dn, })
def setup_dns_partitions(samdb, domainsid, domaindn, forestdn, configdn, serverdn, fill_level): domainzone_dn = "DC=DomainDnsZones,%s" % domaindn forestzone_dn = "DC=ForestDnsZones,%s" % forestdn descriptor = get_dns_partition_descriptor(domainsid) setup_add_ldif(samdb, setup_path("provision_dnszones_partitions.ldif"), { "ZONE_DN": domainzone_dn, "SECDESC" : b64encode(descriptor) }) if fill_level != FILL_SUBDOMAIN: setup_add_ldif(samdb, setup_path("provision_dnszones_partitions.ldif"), { "ZONE_DN": forestzone_dn, "SECDESC" : b64encode(descriptor) }) domainzone_guid = get_domainguid(samdb, domainzone_dn) domainzone_guid = str(uuid.uuid4()) domainzone_dns = ldb.Dn(samdb, domainzone_dn).canonical_ex_str().strip() protected1_desc = get_domain_delete_protected1_descriptor(domainsid) protected2_desc = get_domain_delete_protected2_descriptor(domainsid) setup_add_ldif(samdb, setup_path("provision_dnszones_add.ldif"), { "ZONE_DN": domainzone_dn, "ZONE_GUID": domainzone_guid, "ZONE_DNS": domainzone_dns, "CONFIGDN": configdn, "SERVERDN": serverdn, "LOSTANDFOUND_DESCRIPTOR": b64encode(protected2_desc), "INFRASTRUCTURE_DESCRIPTOR": b64encode(protected1_desc), }) setup_modify_ldif(samdb, setup_path("provision_dnszones_modify.ldif"), { "CONFIGDN": configdn, "SERVERDN": serverdn, "ZONE_DN": domainzone_dn, }) if fill_level != FILL_SUBDOMAIN: forestzone_guid = get_domainguid(samdb, forestzone_dn) forestzone_guid = str(uuid.uuid4()) forestzone_dns = ldb.Dn(samdb, forestzone_dn).canonical_ex_str().strip() setup_add_ldif(samdb, setup_path("provision_dnszones_add.ldif"), { "ZONE_DN": forestzone_dn, "ZONE_GUID": forestzone_guid, "ZONE_DNS": forestzone_dns, "CONFIGDN": configdn, "SERVERDN": serverdn, "LOSTANDFOUND_DESCRIPTOR": b64encode(protected2_desc), "INFRASTRUCTURE_DESCRIPTOR": b64encode(protected1_desc), }) setup_modify_ldif(samdb, setup_path("provision_dnszones_modify.ldif"), { "CONFIGDN": configdn, "SERVERDN": serverdn, "ZONE_DN": forestzone_dn, })
def load_schema(ldif_file): """ Load a schema from the given file into the SamDB """ samdb = samdb_connect() dn = samdb.domain_dn() samdb.transaction_start() try: setup_add_ldif(samdb, ldif_file, { "DOMAINDN": dn, }) except: samdb.transaction_cancel() raise samdb.transaction_commit()
def setup_dns_partitions(samdb, domainsid, domaindn, forestdn, configdn, serverdn): domainzone_dn = "DC=DomainDnsZones,%s" % domaindn forestzone_dn = "DC=ForestDnsZones,%s" % forestdn descriptor = get_dns_partition_descriptor(domainsid) setup_add_ldif( samdb, setup_path("provision_dnszones_partitions.ldif"), { "DOMAINZONE_DN": domainzone_dn, "FORESTZONE_DN": forestzone_dn, "SECDESC": b64encode(descriptor) }) domainzone_guid = get_domainguid(samdb, domainzone_dn) forestzone_guid = get_domainguid(samdb, forestzone_dn) domainzone_guid = str(uuid.uuid4()) forestzone_guid = str(uuid.uuid4()) domainzone_dns = ldb.Dn(samdb, domainzone_dn).canonical_ex_str().strip() forestzone_dns = ldb.Dn(samdb, forestzone_dn).canonical_ex_str().strip() setup_add_ldif( samdb, setup_path("provision_dnszones_add.ldif"), { "DOMAINZONE_DN": domainzone_dn, "FORESTZONE_DN": forestzone_dn, "DOMAINZONE_GUID": domainzone_guid, "FORESTZONE_GUID": forestzone_guid, "DOMAINZONE_DNS": domainzone_dns, "FORESTZONE_DNS": forestzone_dns, "CONFIGDN": configdn, "SERVERDN": serverdn, }) setup_modify_ldif( samdb, setup_path("provision_dnszones_modify.ldif"), { "CONFIGDN": configdn, "SERVERDN": serverdn, "DOMAINZONE_DN": domainzone_dn, "FORESTZONE_DN": forestzone_dn, })
def setup_dns_partitions(samdb, domainsid, domaindn, forestdn, configdn, serverdn): domainzone_dn = "DC=DomainDnsZones,%s" % domaindn forestzone_dn = "DC=ForestDnsZones,%s" % forestdn descriptor = get_dns_partition_descriptor(domainsid) setup_add_ldif(samdb, setup_path("provision_dnszones_partitions.ldif"), { "DOMAINZONE_DN": domainzone_dn, "FORESTZONE_DN": forestzone_dn, "SECDESC" : b64encode(descriptor) }) domainzone_guid = get_domainguid(samdb, domainzone_dn) forestzone_guid = get_domainguid(samdb, forestzone_dn) domainzone_guid = str(uuid.uuid4()) forestzone_guid = str(uuid.uuid4()) domainzone_dns = ldb.Dn(samdb, domainzone_dn).canonical_ex_str().strip() forestzone_dns = ldb.Dn(samdb, forestzone_dn).canonical_ex_str().strip() setup_add_ldif(samdb, setup_path("provision_dnszones_add.ldif"), { "DOMAINZONE_DN": domainzone_dn, "FORESTZONE_DN": forestzone_dn, "DOMAINZONE_GUID": domainzone_guid, "FORESTZONE_GUID": forestzone_guid, "DOMAINZONE_DNS": domainzone_dns, "FORESTZONE_DNS": forestzone_dns, "CONFIGDN": configdn, "SERVERDN": serverdn, }) setup_modify_ldif(samdb, setup_path("provision_dnszones_modify.ldif"), { "CONFIGDN": configdn, "SERVERDN": serverdn, "DOMAINZONE_DN": domainzone_dn, "FORESTZONE_DN": forestzone_dn, })
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 add_dns_accounts(samdb, domaindn): setup_add_ldif(samdb, setup_path("provision_dns_accounts_add.ldif"), { "DOMAINDN": domaindn, })
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""")
msg = samdb.search(base=names.domaindn, scope=samba.ldb.SCOPE_DEFAULT, expression='(sAMAccountName=dns-%s)' % (names.hostname), attrs=['clearTextPassword']) if msg: print "removing sAMAccountName=dns-%s" % (names.hostname) dn = msg[0].dn samdb.delete(dn) except Exception: print "exception while removing sAMAccountName=dns-%s" % (names.hostname) pass setup_add_ldif(secretsdb, setup_path("secrets_dns.ldif"), { "REALM": names.realm, "DNSDOMAIN": names.dnsdomain, "DNS_KEYTAB": dns_keytab_path, "DNSPASS_B64": b64encode(dnspass), "HOSTNAME": names.hostname, "DNSNAME" : '%s.%s' % ( names.netbiosname.lower(), names.dnsdomain.lower()) }) account_created = False count = 0 while not account_created: try: setup_add_ldif(samdb, setup_path("provision_dns_add_samba.ldif"), { "DNSDOMAIN": names.dnsdomain, "DOMAINDN": names.domaindn, "DNSPASS_B64": b64encode(dnspass.encode('utf-16-le')), "HOSTNAME" : names.hostname, "DNSNAME" : '%s.%s' % (
print "removing sAMAccountName=dns-%s" % (names.hostname) dn = msg[0].dn samdb.delete(dn) except Exception: print "exception while removing sAMAccountName=dns-%s" % ( names.hostname) pass setup_add_ldif( secretsdb, setup_path("secrets_dns.ldif"), { "REALM": names.realm, "DNSDOMAIN": names.dnsdomain, "DNS_KEYTAB": dns_keytab_path, "DNSPASS_B64": b64encode(dnspass), "HOSTNAME": names.hostname, "DNSNAME": '%s.%s' % (names.netbiosname.lower(), names.dnsdomain.lower()) }) account_created = False count = 0 while not account_created: try: setup_add_ldif( samdb, setup_path("provision_dns_add_samba.ldif"), { "DNSDOMAIN":