1 # Unix SMB/CIFS implementation.
2 # backend code for provisioning DNS for a Samba4 server
4 # Copyright (C) Kai Blin <kai@samba.org> 2011
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 """DNS-related provisioning"""
25 from samba.ndr import ndr_pack
26 from samba import read_and_sub_file
27 from samba.dcerpc import dnsp
29 class ARecord(dnsp.DnssrvRpcRecord):
30 def __init__(self, ip_addr, serial=1, ttl=3600):
31 super(ARecord, self).__init__()
32 self.wType = dnsp.DNS_TYPE_A
33 self.dwSerial = serial
34 self.dwTtlSeconds = ttl
37 class AAAARecord(dnsp.DnssrvRpcRecord):
38 def __init__(self, ip6_addr, serial=1, ttl=3600):
39 super(AAAARecord, self).__init__()
40 self.wType = dnsp.DNS_TYPE_AAAA
41 self.dwSerial = serial
42 self.dwTtlSeconds = ttl
45 class NSRecord(dnsp.DnssrvRpcRecord):
46 def __init__(self, dns_server, serial=1, ttl=3600):
47 super(NSRecord, self).__init__()
48 self.wType = dnsp.DNS_TYPE_NS
49 self.dwSerial = serial
50 self.dwTtlSeconds = ttl
51 self.data = dns_server
53 class SOARecord(dnsp.DnssrvRpcRecord):
54 def __init__(self, mname, rname, serial=1, refresh=900, retry=600,
55 expire=86400, minimum=3600, ttl=3600):
56 super(SOARecord, self).__init__()
57 self.wType = dnsp.DNS_TYPE_SOA
58 self.dwSerial = serial
59 self.dwTtlSeconds = ttl
69 class SRVRecord(dnsp.DnssrvRpcRecord):
70 def __init__(self, target, port, priority=0, weight=0, serial=1, ttl=3600):
71 super(SRVRecord, self).__init__()
72 self.wType = dnsp.DNS_TYPE_SRV
73 self.dwSerial = serial
74 self.dwTtlSeconds = ttl
76 srv.nameTarget = target
78 srv.wPriority = priority
82 def setup_ad_dns(samdb, names, hostip=None, hostip6=None):
83 domaindn = names.domaindn
84 dnsdomain = names.dnsdomain.lower()
85 hostname = names.netbiosname.lower()
86 dnsname = "%s.%s" % (hostname, dnsdomain)
89 dns_ldif = os.path.join(samba.param.setup_dir(), "provision_dns_add.ldif")
91 dns_data = read_and_sub_file(dns_ldif, {
93 "DNSDOMAIN" : dnsdomain
95 samdb.add_ldif(dns_data, ["relax:0"])
100 # @ entry for the domain
101 at_soa_record = SOARecord(dnsname, "hostmaster.%s" % dnsdomain)
102 soa_subrecords.append(ndr_pack(at_soa_record))
104 at_ns_record = NSRecord(dnsname)
105 soa_subrecords.append(ndr_pack(at_ns_record))
107 if hostip is not None:
109 at_a_record = ARecord(hostip)
110 dns_records.append(ndr_pack(at_a_record))
112 if hostip6 is not None:
113 at_aaaa_record = AAAARecord(hostip6)
114 dns_records.append(ndr_pack(at_aaaa_record))
116 msg = ldb.Message(ldb.Dn(samdb, "DC=@,DC=%s,CN=MicrosoftDNS,CN=System,%s" %\
117 (dnsdomain, domaindn )))
118 msg["objectClass"] = ["top", "dnsNode"]
119 msg["dnsRecord"] = ldb.MessageElement(soa_subrecords + dns_records,
120 ldb.FLAG_MOD_ADD, "dnsRecord")
124 gc_tcp_record = SRVRecord(dnsname, 3268)
125 msg = ldb.Message(ldb.Dn(samdb,
126 "DC=_gc._tcp,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
127 (dnsdomain, domaindn)))
128 msg["objectClass"] = ["top", "dnsNode"]
129 msg["dnsRecord"] = [ndr_pack(gc_tcp_record)]
132 # _gc._tcp.sitename._site record
133 msg = ldb.Message(ldb.Dn(samdb,
134 "DC=_gc._tcp.%s._sites,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
135 (names.sitename, dnsdomain, domaindn)))
136 msg["objectClass"] = ["top", "dnsNode"]
137 msg["dnsRecord"] = [ndr_pack(gc_tcp_record)]
140 # _kerberos._tcp record
141 kerberos_record = SRVRecord(dnsname, 88)
142 msg = ldb.Message(ldb.Dn(samdb,
143 "DC=_kerberos._tcp,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
144 (dnsdomain, domaindn)))
145 msg["objectClass"] = ["top", "dnsNode"]
146 msg["dnsRecord"] = [ndr_pack(kerberos_record)]
149 # _kerberos._tcp.sitename._site record
150 msg = ldb.Message(ldb.Dn(samdb,
151 "DC=_kerberos._tcp.%s._sites,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
152 (site, dnsdomain, domaindn)))
153 msg["objectClass"] = ["top", "dnsNode"]
154 msg["dnsRecord"] = [ndr_pack(kerberos_record)]
157 # _kerberos._udp record
158 msg = ldb.Message(ldb.Dn(samdb,
159 "DC=_kerberos._udp,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
160 (dnsdomain, domaindn)))
161 msg["objectClass"] = ["top", "dnsNode"]
162 msg["dnsRecord"] = [ndr_pack(kerberos_record)]
165 # _kpasswd._tcp record
166 kpasswd_record = SRVRecord(dnsname, 464)
167 msg = ldb.Message(ldb.Dn(samdb,
168 "DC=_kpasswd._tcp,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
169 (dnsdomain, domaindn)))
170 msg["objectClass"] = ["top", "dnsNode"]
171 msg["dnsRecord"] = [ndr_pack(kpasswd_record)]
174 # _kpasswd._udp record
175 msg = ldb.Message(ldb.Dn(samdb,
176 "DC=_kpasswd._udp,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
177 (dnsdomain, domaindn)))
178 msg["objectClass"] = ["top", "dnsNode"]
179 msg["dnsRecord"] = [ndr_pack(kpasswd_record)]
183 ldap_record = SRVRecord(dnsname, 389)
184 msg = ldb.Message(ldb.Dn(samdb,
185 "DC=_ldap._tcp,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
186 (dnsdomain, domaindn)))
187 msg["objectClass"] = ["top", "dnsNode"]
188 msg["dnsRecord"] = [ndr_pack(ldap_record)]
191 # _ldap._tcp.sitename._site record
192 msg = ldb.Message(ldb.Dn(samdb,
193 "DC=_ldap._tcp.%s._site,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
194 (site, dnsdomain, domaindn)))
195 msg["objectClass"] = ["top", "dnsNode"]
196 msg["dnsRecord"] = [ndr_pack(ldap_record)]
200 msdcs_record = NSRecord(dnsname)
201 msg = ldb.Message(ldb.Dn(samdb,
202 "DC=_msdcs,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
203 (dnsdomain, domaindn)))
204 msg["objectClass"] = ["top", "dnsNode"]
205 msg["dnsRecord"] = [ndr_pack(msdcs_record)]
208 # the host's own record
209 # Only do this if there's IP addresses to set up.
210 # This is a bit weird, but the samba4.blackbox.provision.py test apparently
211 # doesn't set up any IPs
212 if len(dns_records) > 0:
213 msg = ldb.Message(ldb.Dn(samdb,
214 "DC=%s,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
215 (hostname, dnsdomain, domaindn)))
216 msg["objectClass"] = ["top", "dnsNode"]
217 msg["dnsRecord"] = ldb.MessageElement(dns_records,
218 ldb.FLAG_MOD_ADD, "dnsRecord")
221 # DomainDnsZones record
222 msg = ldb.Message(ldb.Dn(samdb,
223 "DC=DomainDnsZones,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
224 (dnsdomain, domaindn)))
225 msg["objectClass"] = ["top", "dnsNode"]
226 msg["dnsRecord"] = ldb.MessageElement(dns_records,
227 ldb.FLAG_MOD_ADD, "dnsRecord")