diff options
-rw-r--r-- | source4/scripting/python/samba/provision/__init__.py | 12 | ||||
-rw-r--r-- | source4/scripting/python/samba/provision/sambadns.py | 231 | ||||
-rw-r--r-- | source4/setup/provision_dns_add.ldif | 2 |
3 files changed, 236 insertions, 9 deletions
diff --git a/source4/scripting/python/samba/provision/__init__.py b/source4/scripting/python/samba/provision/__init__.py index 4b2ce7cd22..f2b8c045ac 100644 --- a/source4/scripting/python/samba/provision/__init__.py +++ b/source4/scripting/python/samba/provision/__init__.py @@ -74,6 +74,8 @@ from samba.provision.backend import ( LDBBackend, OpenLDAPBackend, ) +from samba.provision.sambadns import setup_ad_dns + import samba.param import samba.registry from samba.schema import Schema @@ -1101,7 +1103,6 @@ def setup_self_join(samdb, names, machinepass, dnspass, "RIDALLOCATIONEND": str(next_rid + 100 + 499), }) - setup_ad_dns(samdb, names) # This is Samba4 specific and should be replaced by the correct # DNS AD-style setup setup_add_ldif(samdb, setup_path("provision_dns_add_samba.ldif"), { @@ -1114,13 +1115,6 @@ def setup_self_join(samdb, names, machinepass, dnspass, }) -def setup_ad_dns(samdb, names): - setup_add_ldif(samdb, setup_path("provision_dns_add.ldif"), { - "DOMAINDN": names.domaindn, - "DNSNAME" : '%s.%s' % ( - names.netbiosname.lower(), names.dnsdomain.lower()) - }) - def getpolicypath(sysvolpath, dnsdomain, guid): """Return the physical path of policy given its guid. @@ -1769,6 +1763,8 @@ def provision(logger, session_info, credentials, smbconf=None, dnsdomain=names.dnsdomain, dns_keytab_path=paths.dns_keytab, dnspass=dnspass) + setup_ad_dns(samdb, names=names, hostip=hostip, hostip6=hostip6) + domainguid = samdb.searchone(basedn=domaindn, attribute="objectGUID") assert isinstance(domainguid, str) diff --git a/source4/scripting/python/samba/provision/sambadns.py b/source4/scripting/python/samba/provision/sambadns.py new file mode 100644 index 0000000000..6b8561e1b5 --- /dev/null +++ b/source4/scripting/python/samba/provision/sambadns.py @@ -0,0 +1,231 @@ +# Unix SMB/CIFS implementation. +# backend code for provisioning DNS for a Samba4 server +# +# Copyright (C) Kai Blin <kai@samba.org> 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 <http://www.gnu.org/licenses/>. +# + +"""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) + + diff --git a/source4/setup/provision_dns_add.ldif b/source4/setup/provision_dns_add.ldif index 3039bc0485..12ad589ddf 100644 --- a/source4/setup/provision_dns_add.ldif +++ b/source4/setup/provision_dns_add.ldif @@ -16,7 +16,7 @@ objectClass: container displayName: DNS Servers -dn: DC=${DNSNAME},CN=MicrosoftDNS,CN=System,${DOMAINDN} +dn: DC=${DNSDOMAIN},CN=MicrosoftDNS,CN=System,${DOMAINDN} objectClass: dnsZone dn: DC=RootDNSServers,CN=MicrosoftDNS,CN=System,${DOMAINDN} |