# Unix SMB/CIFS implementation. # backend code for provisioning DNS for a Samba4 server # # Copyright (C) Kai Blin 2011 # # 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 . # """DNS-related provisioning""" import os import ldb import samba from samba.ndr import ndr_pack from samba import read_and_sub_file from samba.dcerpc import dnsp class ARecord(dnsp.DnssrvRpcRecord): def __init__(self, ip_addr, serial=1, ttl=3600): super(ARecord, self).__init__() self.wType = dnsp.DNS_TYPE_A self.dwSerial = serial self.dwTtlSeconds = ttl self.data = ip_addr class AAAARecord(dnsp.DnssrvRpcRecord): def __init__(self, ip6_addr, serial=1, ttl=3600): super(AAAARecord, self).__init__() self.wType = dnsp.DNS_TYPE_AAAA self.dwSerial = serial self.dwTtlSeconds = ttl self.data = ip6_addr class NSRecord(dnsp.DnssrvRpcRecord): def __init__(self, dns_server, serial=1, ttl=3600): super(NSRecord, self).__init__() self.wType = dnsp.DNS_TYPE_NS self.dwSerial = serial self.dwTtlSeconds = ttl self.data = dns_server class SOARecord(dnsp.DnssrvRpcRecord): def __init__(self, mname, rname, serial=1, refresh=900, retry=600, expire=86400, minimum=3600, ttl=3600): super(SOARecord, self).__init__() self.wType = dnsp.DNS_TYPE_SOA self.dwSerial = serial self.dwTtlSeconds = ttl soa = dnsp.soa() soa.serial = serial soa.refresh = refresh soa.retry = retry soa.expire = expire soa.mname = mname soa.rname = rname self.data = soa class SRVRecord(dnsp.DnssrvRpcRecord): def __init__(self, target, port, priority=0, weight=0, serial=1, ttl=3600): super(SRVRecord, self).__init__() self.wType = dnsp.DNS_TYPE_SRV self.dwSerial = serial self.dwTtlSeconds = ttl srv = dnsp.srv() srv.nameTarget = target srv.wPort = port srv.wPriority = priority srv.wWeight = weight self.data = srv def setup_ad_dns(samdb, names, hostip=None, hostip6=None): domaindn = names.domaindn dnsdomain = names.dnsdomain.lower() hostname = names.netbiosname.lower() dnsname = "%s.%s" % (hostname, dnsdomain) site = names.sitename dns_ldif = os.path.join(samba.param.setup_dir(), "provision_dns_add.ldif") dns_data = read_and_sub_file(dns_ldif, { "DOMAINDN": domaindn, "DNSDOMAIN" : dnsdomain }) samdb.add_ldif(dns_data, ["relax:0"]) soa_subrecords = [] dns_records = [] # @ entry for the domain at_soa_record = SOARecord(dnsname, "hostmaster.%s" % dnsdomain) soa_subrecords.append(ndr_pack(at_soa_record)) at_ns_record = NSRecord(dnsname) soa_subrecords.append(ndr_pack(at_ns_record)) if hostip is not None: # A record at_a_record = ARecord(hostip) dns_records.append(ndr_pack(at_a_record)) if hostip6 is not None: at_aaaa_record = AAAARecord(hostip6) dns_records.append(ndr_pack(at_aaaa_record)) msg = ldb.Message(ldb.Dn(samdb, "DC=@,DC=%s,CN=MicrosoftDNS,CN=System,%s" %\ (dnsdomain, domaindn ))) msg["objectClass"] = ["top", "dnsNode"] msg["dnsRecord"] = ldb.MessageElement(soa_subrecords + dns_records, ldb.FLAG_MOD_ADD, "dnsRecord") samdb.add(msg) # _gc._tcp record gc_tcp_record = SRVRecord(dnsname, 3268) msg = ldb.Message(ldb.Dn(samdb, "DC=_gc._tcp,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \ (dnsdomain, domaindn))) msg["objectClass"] = ["top", "dnsNode"] msg["dnsRecord"] = [ndr_pack(gc_tcp_record)] samdb.add(msg) # _gc._tcp.sitename._site record msg = ldb.Message(ldb.Dn(samdb, "DC=_gc._tcp.%s._sites,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \ (names.sitename, dnsdomain, domaindn))) msg["objectClass"] = ["top", "dnsNode"] msg["dnsRecord"] = [ndr_pack(gc_tcp_record)] samdb.add(msg) # _kerberos._tcp record kerberos_record = SRVRecord(dnsname, 88) msg = ldb.Message(ldb.Dn(samdb, "DC=_kerberos._tcp,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \ (dnsdomain, domaindn))) msg["objectClass"] = ["top", "dnsNode"] msg["dnsRecord"] = [ndr_pack(kerberos_record)] samdb.add(msg) # _kerberos._tcp.sitename._site record msg = ldb.Message(ldb.Dn(samdb, "DC=_kerberos._tcp.%s._sites,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \ (site, dnsdomain, domaindn))) msg["objectClass"] = ["top", "dnsNode"] msg["dnsRecord"] = [ndr_pack(kerberos_record)] samdb.add(msg) # _kerberos._udp record msg = ldb.Message(ldb.Dn(samdb, "DC=_kerberos._udp,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \ (dnsdomain, domaindn))) msg["objectClass"] = ["top", "dnsNode"] msg["dnsRecord"] = [ndr_pack(kerberos_record)] samdb.add(msg) # _kpasswd._tcp record kpasswd_record = SRVRecord(dnsname, 464) msg = ldb.Message(ldb.Dn(samdb, "DC=_kpasswd._tcp,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \ (dnsdomain, domaindn))) msg["objectClass"] = ["top", "dnsNode"] msg["dnsRecord"] = [ndr_pack(kpasswd_record)] samdb.add(msg) # _kpasswd._udp record msg = ldb.Message(ldb.Dn(samdb, "DC=_kpasswd._udp,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \ (dnsdomain, domaindn))) msg["objectClass"] = ["top", "dnsNode"] msg["dnsRecord"] = [ndr_pack(kpasswd_record)] samdb.add(msg) # _ldap._tcp record ldap_record = SRVRecord(dnsname, 389) msg = ldb.Message(ldb.Dn(samdb, "DC=_ldap._tcp,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \ (dnsdomain, domaindn))) msg["objectClass"] = ["top", "dnsNode"] msg["dnsRecord"] = [ndr_pack(ldap_record)] samdb.add(msg) # _ldap._tcp.sitename._site record msg = ldb.Message(ldb.Dn(samdb, "DC=_ldap._tcp.%s._site,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \ (site, dnsdomain, domaindn))) msg["objectClass"] = ["top", "dnsNode"] msg["dnsRecord"] = [ndr_pack(ldap_record)] samdb.add(msg) # _msdcs record msdcs_record = NSRecord(dnsname) msg = ldb.Message(ldb.Dn(samdb, "DC=_msdcs,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \ (dnsdomain, domaindn))) msg["objectClass"] = ["top", "dnsNode"] msg["dnsRecord"] = [ndr_pack(msdcs_record)] samdb.add(msg) # the host's own record # Only do this if there's IP addresses to set up. # This is a bit weird, but the samba4.blackbox.provision.py test apparently # doesn't set up any IPs if len(dns_records) > 0: msg = ldb.Message(ldb.Dn(samdb, "DC=%s,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \ (hostname, dnsdomain, domaindn))) msg["objectClass"] = ["top", "dnsNode"] msg["dnsRecord"] = ldb.MessageElement(dns_records, ldb.FLAG_MOD_ADD, "dnsRecord") samdb.add(msg) # DomainDnsZones record msg = ldb.Message(ldb.Dn(samdb, "DC=DomainDnsZones,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \ (dnsdomain, domaindn))) msg["objectClass"] = ["top", "dnsNode"] msg["dnsRecord"] = ldb.MessageElement(dns_records, ldb.FLAG_MOD_ADD, "dnsRecord") samdb.add(msg)