s4 provision: Add some of the AD-specific DNS records to the directory
[mat/samba.git] / source4 / scripting / python / samba / provision / sambadns.py
1 # Unix SMB/CIFS implementation.
2 # backend code for provisioning DNS for a Samba4 server
3 #
4 # Copyright (C) Kai Blin <kai@samba.org> 2011
5 #
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.
10 #
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.
15 #
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/>.
18 #
19
20 """DNS-related provisioning"""
21
22 import os
23 import ldb
24 import samba
25 from samba.ndr import ndr_pack
26 from samba import read_and_sub_file
27 from samba.dcerpc import dnsp
28
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
35         self.data = ip_addr
36
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
43         self.data = ip6_addr
44
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
52
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
60         soa = dnsp.soa()
61         soa.serial = serial
62         soa.refresh = refresh
63         soa.retry = retry
64         soa.expire = expire
65         soa.mname = mname
66         soa.rname = rname
67         self.data = soa
68
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
75         srv = dnsp.srv()
76         srv.nameTarget = target
77         srv.wPort = port
78         srv.wPriority = priority
79         srv.wWeight = weight
80         self.data = srv
81
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)
87     site = names.sitename
88
89     dns_ldif = os.path.join(samba.param.setup_dir(), "provision_dns_add.ldif")
90
91     dns_data = read_and_sub_file(dns_ldif, {
92               "DOMAINDN": domaindn,
93               "DNSDOMAIN" : dnsdomain
94               })
95     samdb.add_ldif(dns_data, ["relax:0"])
96
97     soa_subrecords = []
98     dns_records = []
99
100     # @ entry for the domain
101     at_soa_record = SOARecord(dnsname, "hostmaster.%s" % dnsdomain)
102     soa_subrecords.append(ndr_pack(at_soa_record))
103
104     at_ns_record = NSRecord(dnsname)
105     soa_subrecords.append(ndr_pack(at_ns_record))
106
107     if hostip is not None:
108         # A record
109         at_a_record = ARecord(hostip)
110         dns_records.append(ndr_pack(at_a_record))
111
112     if hostip6 is not None:
113         at_aaaa_record = AAAARecord(hostip6)
114         dns_records.append(ndr_pack(at_aaaa_record))
115
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")
121     samdb.add(msg)
122
123     # _gc._tcp record
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)]
130     samdb.add(msg)
131
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)]
138     samdb.add(msg)
139
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)]
147     samdb.add(msg)
148
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)]
155     samdb.add(msg)
156
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)]
163     samdb.add(msg)
164
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)]
172     samdb.add(msg)
173
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)]
180     samdb.add(msg)
181
182     # _ldap._tcp 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)]
189     samdb.add(msg)
190
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)]
197     samdb.add(msg)
198
199     # _msdcs 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)]
206     samdb.add(msg)
207
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")
219         samdb.add(msg)
220
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")
228
229         samdb.add(msg)
230
231