Example #1
0
def create_named_conf(paths, realm, dnsdomain, dns_backend):
    """Write out a file containing zone statements suitable for inclusion in a
    named.conf file (including GSS-TSIG configuration).

    :param paths: all paths
    :param realm: Realm name
    :param dnsdomain: DNS Domain name
    :param dns_backend: DNS backend type
    :param keytab_name: File name of DNS keytab file
    """

    if dns_backend == "BIND9_FLATFILE":
        setup_file(
            setup_path("named.conf"), paths.namedconf, {
                "DNSDOMAIN": dnsdomain,
                "REALM": realm,
                "ZONE_FILE": paths.dns,
                "REALM_WC": "*." + ".".join(realm.split(".")[1:]),
                "NAMED_CONF": paths.namedconf,
                "NAMED_CONF_UPDATE": paths.namedconf_update
            })

        setup_file(setup_path("named.conf.update"), paths.namedconf_update)

    elif dns_backend == "BIND9_DLZ":
        setup_file(
            setup_path("named.conf.dlz"), paths.namedconf, {
                "NAMED_CONF": paths.namedconf,
                "MODULESDIR": samba.param.modules_dir(),
            })
Example #2
0
def create_named_conf(paths, realm, dnsdomain, dns_backend, logger):
    """Write out a file containing zone statements suitable for inclusion in a
    named.conf file (including GSS-TSIG configuration).

    :param paths: all paths
    :param realm: Realm name
    :param dnsdomain: DNS Domain name
    :param dns_backend: DNS backend type
    :param keytab_name: File name of DNS keytab file
    :param logger: Logger object
    """

    # TODO: This really should have been done as a top level import.
    # It is done here to avoid a depencency loop.  That is, we move
    # ProvisioningError to another file, and have all the provision
    # scripts import it from there.

    from samba.provision import ProvisioningError

    if dns_backend == "BIND9_FLATFILE":
        setup_file(setup_path("named.conf"), paths.namedconf, {
                    "DNSDOMAIN": dnsdomain,
                    "REALM": realm,
                    "ZONE_FILE": paths.dns,
                    "REALM_WC": "*." + ".".join(realm.split(".")[1:]),
                    "NAMED_CONF": paths.namedconf,
                    "NAMED_CONF_UPDATE": paths.namedconf_update
                    })

        setup_file(setup_path("named.conf.update"), paths.namedconf_update)

    elif dns_backend == "BIND9_DLZ":
        bind_info = subprocess.Popen(['named -V'], shell=True,
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.STDOUT,
                                     cwd='.').communicate()[0]
        bind9_8 = '#'
        bind9_9 = '#'
        bind9_10 = '#'
        bind9_11 = '#'
        if bind_info.upper().find('BIND 9.8') != -1:
            bind9_8 = ''
        elif bind_info.upper().find('BIND 9.9') != -1:
            bind9_9 = ''
        elif bind_info.upper().find('BIND 9.10') != -1:
            bind9_10 = ''
        elif bind_info.upper().find('BIND 9.11') != -1:
            bind9_11 = ''
        elif bind_info.upper().find('BIND 9.7') != -1:
            raise ProvisioningError("DLZ option incompatible with BIND 9.7.")
        else:
            logger.warning("BIND version unknown, please modify %s manually." % paths.namedconf)
        setup_file(setup_path("named.conf.dlz"), paths.namedconf, {
                    "NAMED_CONF": paths.namedconf,
                    "MODULESDIR" : samba.param.modules_dir(),
                    "BIND9_8" : bind9_8,
                    "BIND9_9" : bind9_9,
                    "BIND9_10" : bind9_10,
                    "BIND9_11" : bind9_11
                    })
def create_named_conf(paths, realm, dnsdomain, dns_backend):
    """Write out a file containing zone statements suitable for inclusion in a
    named.conf file (including GSS-TSIG configuration).

    :param paths: all paths
    :param realm: Realm name
    :param dnsdomain: DNS Domain name
    :param dns_backend: DNS backend type
    :param keytab_name: File name of DNS keytab file
    """

    if dns_backend == "BIND9_FLATFILE":
        setup_file(setup_path("named.conf"), paths.namedconf, {
                    "DNSDOMAIN": dnsdomain,
                    "REALM": realm,
                    "ZONE_FILE": paths.dns,
                    "REALM_WC": "*." + ".".join(realm.split(".")[1:]),
                    "NAMED_CONF": paths.namedconf,
                    "NAMED_CONF_UPDATE": paths.namedconf_update
                    })

        setup_file(setup_path("named.conf.update"), paths.namedconf_update)

    elif dns_backend == "BIND9_DLZ":
        setup_file(setup_path("named.conf.dlz"), paths.namedconf, {
                    "NAMED_CONF": paths.namedconf,
                    "MODULESDIR" : samba.param.modules_dir(),
                    })
Example #4
0
def create_zone_file(lp, logger, paths, targetdir, dnsdomain,
                     hostip, hostip6, hostname, realm, domainguid,
                     ntdsguid, site):
    """Write out a DNS zone file, from the info in the current database.

    :param paths: paths object
    :param dnsdomain: DNS Domain name
    :param domaindn: DN of the Domain
    :param hostip: Local IPv4 IP
    :param hostip6: Local IPv6 IP
    :param hostname: Local hostname
    :param realm: Realm name
    :param domainguid: GUID of the domain.
    :param ntdsguid: GUID of the hosts nTDSDSA record.
    """
    assert isinstance(domainguid, str)

    if hostip6 is not None:
        hostip6_base_line = "            IN AAAA    " + hostip6
        hostip6_host_line = hostname + "        IN AAAA    " + hostip6
        gc_msdcs_ip6_line = "gc._msdcs               IN AAAA    " + hostip6
    else:
        hostip6_base_line = ""
        hostip6_host_line = ""
        gc_msdcs_ip6_line = ""

    if hostip is not None:
        hostip_base_line = "            IN A    " + hostip
        hostip_host_line = hostname + "        IN A    " + hostip
        gc_msdcs_ip_line = "gc._msdcs               IN A    " + hostip
    else:
        hostip_base_line = ""
        hostip_host_line = ""
        gc_msdcs_ip_line = ""

    setup_file(setup_path("provision.zone"), paths.dns, {
            "HOSTNAME": hostname,
            "DNSDOMAIN": dnsdomain,
            "REALM": realm,
            "HOSTIP_BASE_LINE": hostip_base_line,
            "HOSTIP_HOST_LINE": hostip_host_line,
            "DOMAINGUID": domainguid,
            "DATESTRING": time.strftime("%Y%m%d%H"),
            "DEFAULTSITE": site,
            "NTDSGUID": ntdsguid,
            "HOSTIP6_BASE_LINE": hostip6_base_line,
            "HOSTIP6_HOST_LINE": hostip6_host_line,
            "GC_MSDCS_IP_LINE": gc_msdcs_ip_line,
            "GC_MSDCS_IP6_LINE": gc_msdcs_ip6_line,
    })

    if paths.bind_gid is not None:
        try:
            os.chown(paths.dns, -1, paths.bind_gid)
            # chmod needed to cope with umask
            os.chmod(paths.dns, 0o664)
        except OSError:
            if 'SAMBA_SELFTEST' not in os.environ:
                logger.error("Failed to chown %s to bind gid %u" % (
                    paths.dns, paths.bind_gid))
Example #5
0
def secretsdb_setup_dns(secretsdb, names, private_dir, realm, dnsdomain,
                        dns_keytab_path, dnspass, key_version_number):
    """Add DNS specific bits to a secrets database.

    :param secretsdb: Ldb Handle to the secrets database
    :param names: Names shortcut
    :param machinepass: Machine password
    """
    try:
        os.unlink(os.path.join(private_dir, dns_keytab_path))
    except OSError:
        pass

    if key_version_number is None:
        key_version_number = 1

    setup_ldb(
        secretsdb, setup_path("secrets_dns.ldif"), {
            "REALM":
            realm,
            "DNSDOMAIN":
            dnsdomain,
            "DNS_KEYTAB":
            dns_keytab_path,
            "DNSPASS_B64":
            b64encode(dnspass.encode('utf-8')),
            "KEY_VERSION_NUMBER":
            str(key_version_number),
            "HOSTNAME":
            names.hostname,
            "DNSNAME":
            '%s.%s' % (names.netbiosname.lower(), names.dnsdomain.lower())
        })
Example #6
0
def secretsdb_setup_dns(secretsdb, names, private_dir, binddns_dir, realm,
                        dnsdomain, dns_keytab_path, dnspass, key_version_number):
    """Add DNS specific bits to a secrets database.

    :param secretsdb: Ldb Handle to the secrets database
    :param names: Names shortcut
    :param machinepass: Machine password
    """
    try:
        os.unlink(os.path.join(private_dir, dns_keytab_path))
        os.unlink(os.path.join(binddns_dir, dns_keytab_path))
    except OSError:
        pass

    if key_version_number is None:
        key_version_number = 1

    # This will create the dns.keytab file in the private_dir when it is
    # commited!
    setup_ldb(secretsdb, setup_path("secrets_dns.ldif"), {
            "REALM": realm,
            "DNSDOMAIN": dnsdomain,
            "DNS_KEYTAB": dns_keytab_path,
            "DNSPASS_B64": b64encode(dnspass.encode('utf-8')).decode('utf8'),
            "KEY_VERSION_NUMBER": str(key_version_number),
            "HOSTNAME": names.hostname,
            "DNSNAME" : '%s.%s' % (
                names.netbiosname.lower(), names.dnsdomain.lower())
            })
Example #7
0
def secretsdb_setup_dns(secretsdb, names, private_dir, realm,
                        dnsdomain, dns_keytab_path, dnspass, key_version_number):
    """Add DNS specific bits to a secrets database.

    :param secretsdb: Ldb Handle to the secrets database
    :param names: Names shortcut
    :param machinepass: Machine password
    """
    try:
        os.unlink(os.path.join(private_dir, dns_keytab_path))
    except OSError:
        pass

    if key_version_number is None:
        key_version_number = 1

    setup_ldb(secretsdb, setup_path("secrets_dns.ldif"), {
            "REALM": realm,
            "DNSDOMAIN": dnsdomain,
            "DNS_KEYTAB": dns_keytab_path,
            "DNSPASS_B64": b64encode(dnspass),
            "KEY_VERSION_NUMBER": str(key_version_number),
            "HOSTNAME": names.hostname,
            "DNSNAME" : '{0!s}.{1!s}'.format(
                names.netbiosname.lower(), names.dnsdomain.lower())
            })
Example #8
0
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()

    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"), {
            "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,
            "LOSTANDFOUND_DESCRIPTOR": b64encode(protected2_desc),
            "INFRASTRUCTURE_DESCRIPTOR": b64encode(protected1_desc),
        })

    setup_modify_ldif(
        samdb, setup_path("provision_dnszones_modify.ldif"), {
            "CONFIGDN": configdn,
            "SERVERDN": serverdn,
            "DOMAINZONE_DN": domainzone_dn,
            "FORESTZONE_DN": forestzone_dn,
        })
Example #9
0
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()

    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"),
        {
            "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,
            "LOSTANDFOUND_DESCRIPTOR": b64encode(protected2_desc),
            "INFRASTRUCTURE_DESCRIPTOR": b64encode(protected1_desc),
        },
    )

    setup_modify_ldif(
        samdb,
        setup_path("provision_dnszones_modify.ldif"),
        {"CONFIGDN": configdn, "SERVERDN": serverdn, "DOMAINZONE_DN": domainzone_dn, "FORESTZONE_DN": forestzone_dn},
    )
Example #10
0
    def __init__(self,
                 samdb,
                 verbose=False,
                 fix=False,
                 add_update_container=True):
        """
        :param samdb: LDB database
        :param verbose: Show the ldif changes
        :param fix: Apply the update if the container is missing
        :param add_update_container: Add the container at the end of the change
        :raise ForestUpdateException:
        """
        from samba.ms_forest_updates_markdown import read_ms_markdown

        self.samdb = samdb
        self.fix = fix
        self.verbose = verbose
        self.add_update_container = add_update_container
        # TODO In future we should check for inconsistencies when it claims it has been done
        self.check_update_applied = False

        self.config_dn = self.samdb.get_config_basedn()
        self.domain_dn = self.samdb.domain_dn()
        self.schema_dn = self.samdb.get_schema_basedn()

        self.sd_utils = sd_utils.SDUtils(samdb)
        self.domain_sid = security.dom_sid(samdb.get_domain_sid())

        self.forestupdate_container = self.samdb.get_config_basedn()
        if not self.forestupdate_container.add_child(
                "CN=Operations,CN=ForestUpdates"):
            raise ForestUpdateException(
                "Failed to add forest update container child")

        self.revision_object = self.samdb.get_config_basedn()
        if not self.revision_object.add_child(
                "CN=ActiveDirectoryUpdate,CN=ForestUpdates"):
            raise ForestUpdateException("Failed to add revision object child")

        # Store the result of parsing the markdown in a dictionary
        self.stored_ldif = {}
        read_ms_markdown(
            setup_path("adprep/WindowsServerDocs/Forest-Wide-Updates.md"),
            out_dict=self.stored_ldif)
Example #11
0
def create_named_txt(path, realm, dnsdomain, dnsname, private_dir,
    keytab_name):
    """Write out a file containing zone statements suitable for inclusion in a
    named.conf file (including GSS-TSIG configuration).

    :param path: Path of the new named.conf file.
    :param realm: Realm name
    :param dnsdomain: DNS Domain name
    :param private_dir: Path to private directory
    :param keytab_name: File name of DNS keytab file
    """
    setup_file(setup_path("named.txt"), path, {
            "DNSDOMAIN": dnsdomain,
            "DNSNAME" : dnsname,
            "REALM": realm,
            "DNS_KEYTAB": keytab_name,
            "DNS_KEYTAB_ABS": os.path.join(private_dir, keytab_name),
            "PRIVATE_DIR": private_dir
        })
def create_named_txt(path, realm, dnsdomain, dnsname, private_dir,
    keytab_name):
    """Write out a file containing zone statements suitable for inclusion in a
    named.conf file (including GSS-TSIG configuration).

    :param path: Path of the new named.conf file.
    :param realm: Realm name
    :param dnsdomain: DNS Domain name
    :param private_dir: Path to private directory
    :param keytab_name: File name of DNS keytab file
    """
    setup_file(setup_path("named.txt"), path, {
            "DNSDOMAIN": dnsdomain,
            "DNSNAME" : dnsname,
            "REALM": realm,
            "DNS_KEYTAB": keytab_name,
            "DNS_KEYTAB_ABS": os.path.join(private_dir, keytab_name),
            "PRIVATE_DIR": private_dir
        })
def secretsdb_setup_dns(secretsdb, names, private_dir, realm,
                        dnsdomain, dns_keytab_path, dnspass):
    """Add DNS specific bits to a secrets database.

    :param secretsdb: Ldb Handle to the secrets database
    :param names: Names shortcut
    :param machinepass: Machine password
    """
    try:
        os.unlink(os.path.join(private_dir, dns_keytab_path))
    except OSError:
        pass

    setup_ldb(secretsdb, setup_path("secrets_dns.ldif"), {
            "REALM": realm,
            "DNSDOMAIN": dnsdomain,
            "DNS_KEYTAB": dns_keytab_path,
            "DNSPASS_B64": b64encode(dnspass),
            "HOSTNAME": names.hostname,
            "DNSNAME" : '%s.%s' % (
                names.netbiosname.lower(), names.dnsdomain.lower())
            })
Example #14
0
    def __init__(self, samdb, verbose=False, fix=False,
                 add_update_container=True):
        """
        :param samdb: LDB database
        :param verbose: Show the ldif changes
        :param fix: Apply the update if the container is missing
        :param add_update_container: Add the container at the end of the change
        :raise ForestUpdateException:
        """
        from samba.ms_forest_updates_markdown import read_ms_markdown

        self.samdb = samdb
        self.fix = fix
        self.verbose = verbose
        self.add_update_container = add_update_container
        # TODO In future we should check for inconsistencies when it claims it has been done
        self.check_update_applied = False

        self.config_dn = self.samdb.get_config_basedn()
        self.domain_dn = self.samdb.domain_dn()
        self.schema_dn = self.samdb.get_schema_basedn()

        self.sd_utils = sd_utils.SDUtils(samdb)
        self.domain_sid = security.dom_sid(samdb.get_domain_sid())

        self.forestupdate_container = self.samdb.get_config_basedn()
        if not self.forestupdate_container.add_child("CN=Operations,CN=ForestUpdates"):
            raise ForestUpdateException("Failed to add forest update container child")

        self.revision_object = self.samdb.get_config_basedn()
        if not self.revision_object.add_child("CN=ActiveDirectoryUpdate,CN=ForestUpdates"):
            raise ForestUpdateException("Failed to add revision object child")

        # Store the result of parsing the markdown in a dictionary
        self.stored_ldif = {}
        read_ms_markdown(setup_path("adprep/WindowsServerDocs/Forest-Wide-Updates.md"),
                         out_dict=self.stored_ldif)
Example #15
0
            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
Example #16
0
	except Exception:
		print "Adding dns-%s account" % names.hostname
	
		try:
			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,
def create_dns_update_list(lp, logger, paths):
    """Write out a dns_update_list file"""
    # note that we use no variable substitution on this file
    # the substitution is done at runtime by samba_dnsupdate, samba_spnupdate
    setup_file(setup_path("dns_update_list"), paths.dns_update_list, None)
    setup_file(setup_path("spn_update_list"), paths.spn_update_list, None)
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_zone_file(lp, logger, paths, targetdir, dnsdomain,
                     hostip, hostip6, hostname, realm, domainguid,
                     ntdsguid, site):
    """Write out a DNS zone file, from the info in the current database.

    :param paths: paths object
    :param dnsdomain: DNS Domain name
    :param domaindn: DN of the Domain
    :param hostip: Local IPv4 IP
    :param hostip6: Local IPv6 IP
    :param hostname: Local hostname
    :param realm: Realm name
    :param domainguid: GUID of the domain.
    :param ntdsguid: GUID of the hosts nTDSDSA record.
    """
    assert isinstance(domainguid, str)

    if hostip6 is not None:
        hostip6_base_line = "            IN AAAA    " + hostip6
        hostip6_host_line = hostname + "        IN AAAA    " + hostip6
        gc_msdcs_ip6_line = "gc._msdcs               IN AAAA    " + hostip6
    else:
        hostip6_base_line = ""
        hostip6_host_line = ""
        gc_msdcs_ip6_line = ""

    if hostip is not None:
        hostip_base_line = "            IN A    " + hostip
        hostip_host_line = hostname + "        IN A    " + hostip
        gc_msdcs_ip_line = "gc._msdcs               IN A    " + hostip
    else:
        hostip_base_line = ""
        hostip_host_line = ""
        gc_msdcs_ip_line = ""

    # we need to freeze the zone while we update the contents
    if targetdir is None:
        rndc = ' '.join(lp.get("rndc command"))
        os.system(rndc + " freeze " + lp.get("realm"))

    setup_file(setup_path("provision.zone"), paths.dns, {
            "HOSTNAME": hostname,
            "DNSDOMAIN": dnsdomain,
            "REALM": realm,
            "HOSTIP_BASE_LINE": hostip_base_line,
            "HOSTIP_HOST_LINE": hostip_host_line,
            "DOMAINGUID": domainguid,
            "DATESTRING": time.strftime("%Y%m%d%H"),
            "DEFAULTSITE": site,
            "NTDSGUID": ntdsguid,
            "HOSTIP6_BASE_LINE": hostip6_base_line,
            "HOSTIP6_HOST_LINE": hostip6_host_line,
            "GC_MSDCS_IP_LINE": gc_msdcs_ip_line,
            "GC_MSDCS_IP6_LINE": gc_msdcs_ip6_line,
        })

    if paths.bind_gid is not None:
        try:
            os.chown(paths.dns, -1, paths.bind_gid)
            # chmod needed to cope with umask
            os.chmod(paths.dns, 0664)
        except OSError:
            if not os.environ.has_key('SAMBA_SELFTEST'):
                logger.error("Failed to chown %s to bind gid %u" % (
                    paths.dns, paths.bind_gid))

    if targetdir is None:
        os.system(rndc + " unfreeze " + lp.get("realm"))
def add_dns_accounts(samdb, domaindn):
    setup_add_ldif(samdb, setup_path("provision_dns_accounts_add.ldif"), {
        "DOMAINDN": domaindn,
        })
Example #21
0
def create_dns_update_list(lp, logger, paths):
    """Write out a dns_update_list file"""
    # note that we use no variable substitution on this file
    # the substitution is done at runtime by samba_dnsupdate, samba_spnupdate
    setup_file(setup_path("dns_update_list"), paths.dns_update_list, None)
    setup_file(setup_path("spn_update_list"), paths.spn_update_list, None)
Example #22
0
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""")
Example #23
0
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""")
Example #24
0
def add_dns_accounts(samdb, domaindn):
    setup_add_ldif(samdb, setup_path("provision_dns_accounts_add.ldif"), {
        "DOMAINDN": domaindn,
    })