f0d7e283110c500bace4e3064bbf23437b5d2984
[samba.git] / source4 / rpc_server / dnsserver / dnsutils.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    DNS Server
5
6    Copyright (C) Amitay Isaacs 2011
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "dnsserver.h"
24 #include "rpc_server/common/common.h"
25 #include "dsdb/samdb/samdb.h"
26 #include "lib/socket/netif.h"
27 #include "lib/util/util_net.h"
28
29 static struct DNS_ADDR_ARRAY *fill_dns_addr_array(TALLOC_CTX *mem_ctx,
30                                            struct loadparm_context *lp_ctx,
31                                            bool listen_only)
32 {
33         struct interface *ifaces;
34         int num_interfaces, i;
35         struct DNS_ADDR_ARRAY *dns_addr_array;
36         const char *ipstr;
37         bool have_ipv4, have_ipv6;
38         uint16_t family;
39
40         have_ipv4 = have_ipv6 = false;
41
42         if (!listen_only) {
43                 /*
44                   Return all interfaces from kernel
45                   Not implemented!
46                 */
47                 return NULL;
48         }
49
50         /* Only the used interfaces */
51         load_interface_list(mem_ctx, lp_ctx, &ifaces);
52         num_interfaces = iface_list_count(ifaces);
53
54         dns_addr_array = talloc_zero(mem_ctx, struct DNS_ADDR_ARRAY);
55         if (dns_addr_array == NULL) {
56                 goto nomem;
57         }
58         dns_addr_array->MaxCount = num_interfaces;
59         dns_addr_array->AddrCount = num_interfaces;
60         if (num_interfaces == 0) {
61                 goto nomem;
62         }
63
64         dns_addr_array->AddrArray = talloc_zero_array(mem_ctx, struct DNS_ADDR,
65                                                       num_interfaces);
66         if (!dns_addr_array->AddrArray) {
67                 TALLOC_FREE(dns_addr_array);
68                 goto nomem;
69         }
70
71         for (i = 0; i < num_interfaces; i++) {
72                 ipstr = iface_list_n_ip(ifaces, i);
73                 if (is_ipaddress_v4(ipstr)) {
74                         have_ipv4 = true;
75                         dns_addr_array->AddrArray[i].MaxSa[0] = 0x02;
76                         inet_pton(AF_INET, ipstr,
77                                   &dns_addr_array->AddrArray[i].MaxSa[4]);
78                 } else {
79                         have_ipv6 = true;
80                         dns_addr_array->AddrArray[i].MaxSa[0] = 0x17;
81                         inet_pton(AF_INET6, ipstr,
82                                   &dns_addr_array->AddrArray[i].MaxSa[8]);
83                 }
84         }
85
86         if (have_ipv4 && have_ipv6) {
87                 family = 0;   /* mixed: MS-DNSP */
88         } else if (have_ipv4 && !have_ipv6) {
89                 family = AF_INET;
90         } else {
91                 family = AF_INET6;
92         }
93         dns_addr_array->Family = family;
94
95 nomem:
96         talloc_free(ifaces);
97         return dns_addr_array;
98 }
99
100 struct dnsserver_serverinfo *dnsserver_init_serverinfo(TALLOC_CTX *mem_ctx,
101                                                         struct loadparm_context *lp_ctx,
102                                                         struct ldb_context *samdb)
103 {
104         struct dnsserver_serverinfo *serverinfo;
105         struct dcerpc_server_info *dinfo;
106         struct ldb_dn *domain_dn, *forest_dn;
107
108         serverinfo = talloc_zero(mem_ctx, struct dnsserver_serverinfo);
109         if (serverinfo == NULL) {
110                 return NULL;
111         }
112
113         dinfo = lpcfg_dcerpc_server_info(mem_ctx, lp_ctx);
114         if (dinfo) {
115                 serverinfo->dwVersion = (dinfo->version_build & 0x0000FFFF) << 16 |
116                                 (dinfo->version_minor & 0x000000FF) << 8 |
117                                 (dinfo->version_major & 0x000000FF);
118                 talloc_free(dinfo);
119         } else {
120                 serverinfo->dwVersion = 0x0ECE0205; /* build, os_minor, os_major */;
121         }
122
123         serverinfo->fBootMethod = DNS_BOOT_METHOD_DIRECTORY;
124         serverinfo->fAdminConfigured = 0;
125         serverinfo->fAllowUpdate = 1;
126         serverinfo->fDsAvailable = 1;
127
128         serverinfo->pszServerName = talloc_asprintf(mem_ctx, "%s.%s",
129                                         lpcfg_netbios_name(lp_ctx),
130                                         lpcfg_dnsdomain(lp_ctx));
131
132         domain_dn = ldb_get_default_basedn(samdb);
133         forest_dn = ldb_get_root_basedn(samdb);
134
135         serverinfo->pszDsContainer = talloc_asprintf(mem_ctx,
136                                         "CN=MicrosoftDNS,DC=DomainDnsZones,%s",
137                                         ldb_dn_get_linearized(domain_dn));
138
139         serverinfo->dwDsForestVersion = dsdb_forest_functional_level(samdb);
140         serverinfo->dwDsDomainVersion = dsdb_functional_level(samdb);
141         serverinfo->dwDsDsaVersion = 4; /* need to do ldb search here */
142
143         serverinfo->pszDomainName = samdb_dn_to_dns_domain(mem_ctx, domain_dn);
144         serverinfo->pszForestName = samdb_dn_to_dns_domain(mem_ctx, forest_dn);
145
146         serverinfo->pszDomainDirectoryPartition = talloc_asprintf(mem_ctx,
147                                                         "DC=DomainDnsZones,%s",
148                                                         ldb_dn_get_linearized(domain_dn));
149         serverinfo->pszForestDirectoryPartition = talloc_asprintf(mem_ctx,
150                                                         "DC=ForestDnsZones,%s",
151                                                         ldb_dn_get_linearized(forest_dn));
152         /* IP addresses on which the DNS server listens for DNS requests */
153         serverinfo->aipListenAddrs = fill_dns_addr_array(mem_ctx, lp_ctx, true);
154
155         /* All IP addresses available on the server
156          * Not implemented!
157          * Use same as listen addresses
158          */
159         serverinfo->aipServerAddrs = serverinfo->aipListenAddrs;
160
161         serverinfo->aipForwarders = NULL;
162
163         serverinfo->aipLogFilter = NULL;
164         serverinfo->pwszLogFilePath = NULL;
165
166         serverinfo->dwLogLevel = 0;
167         serverinfo->dwDebugLevel = 0;
168         serverinfo->dwEventLogLevel = DNS_EVENT_LOG_INFORMATION_TYPE;
169         serverinfo->dwLogFileMaxSize = 0;
170
171         serverinfo->dwForwardTimeout = 3; /* seconds (default) */
172         serverinfo->dwRpcProtocol = 5;
173         serverinfo->dwNameCheckFlag = DNS_ALLOW_MULTIBYTE_NAMES;
174         serverinfo->cAddressAnswerLimit = 0;
175         serverinfo->dwRecursionRetry = 3;       /* seconds (default) */
176         serverinfo->dwRecursionTimeout = 8;     /* seconds (default) */
177         serverinfo->dwMaxCacheTtl = 0x00015180; /* 1 day (default) */
178         serverinfo->dwDsPollingInterval = 0xB4; /* 3 minutes (default) */
179         serverinfo->dwLocalNetPriorityNetMask = 0x000000FF;
180
181         serverinfo->dwScavengingInterval = 0;
182         serverinfo->dwDefaultRefreshInterval = 0xA8;   /* 7 days in hours */
183         serverinfo->dwDefaultNoRefreshInterval = 0xA8; /* 7 days in hours */
184
185         serverinfo->dwLastScavengeTime = 0;
186
187         serverinfo->fAutoReverseZones = 0;
188         serverinfo->fAutoCacheUpdate = 0;
189
190         serverinfo->fRecurseAfterForwarding = 0;
191         serverinfo->fForwardDelegations = 1;
192         serverinfo->fNoRecursion = 0;
193         serverinfo->fSecureResponses = 0;
194
195         serverinfo->fRoundRobin = 1;
196         serverinfo->fLocalNetPriority = 0;
197
198         serverinfo->fBindSecondaries = 0;
199         serverinfo->fWriteAuthorityNs = 0;
200
201         serverinfo->fStrictFileParsing = 0;
202         serverinfo->fLooseWildcarding = 0 ;
203         serverinfo->fDefaultAgingState = 0;
204
205         return serverinfo;
206 }
207
208
209 struct dnsserver_zoneinfo *dnsserver_init_zoneinfo(struct dnsserver_zone *zone,
210                                                 struct dnsserver_serverinfo *serverinfo)
211 {
212         struct dnsserver_zoneinfo *zoneinfo;
213         uint32_t fReverse;
214         const char *revzone = "in-addr.arpa";
215         const char *revzone6 = "ip6.arpa";
216         int len1, len2;
217
218         zoneinfo = talloc_zero(zone, struct dnsserver_zoneinfo);
219         if (zoneinfo == NULL) {
220                 return NULL;
221         }
222
223         /* If the zone name ends with in-addr.arpa, it's reverse zone */
224         /* If the zone name ends with ip6.arpa, it's reverse zone (IPv6) */
225         fReverse = 0;
226         len1 = strlen(zone->name);
227         len2 = strlen(revzone);
228         if (len1 > len2 && strcasecmp(&zone->name[len1-len2], revzone) == 0) {
229                 fReverse = 1;
230         } else {
231                 len2 = strlen(revzone6);
232                 if (len1 > len2 && strcasecmp(&zone->name[len1-len2], revzone6) == 0) {
233                         fReverse = 1;
234                 }
235         }
236
237         zoneinfo->Version = 0x32;
238         zoneinfo->Flags = DNS_RPC_ZONE_DSINTEGRATED;
239
240         if (strcmp(zone->name, ".") == 0) {
241                 zoneinfo->dwZoneType = DNS_ZONE_TYPE_CACHE;
242                 zoneinfo->fAllowUpdate = DNS_ZONE_UPDATE_OFF;
243                 zoneinfo->fSecureSecondaries = DNS_ZONE_SECSECURE_NO_SECURITY;
244                 zoneinfo->fNotifyLevel = DNS_ZONE_NOTIFY_OFF;
245                 zoneinfo->dwNoRefreshInterval = 0;
246                 zoneinfo->dwRefreshInterval = 0;
247         } else {
248                 zoneinfo->Flags |= DNS_RPC_ZONE_UPDATE_SECURE;
249                 zoneinfo->dwZoneType = DNS_ZONE_TYPE_PRIMARY;
250                 zoneinfo->fAllowUpdate = DNS_ZONE_UPDATE_SECURE;
251                 zoneinfo->fSecureSecondaries = DNS_ZONE_SECSECURE_NO_XFER;
252                 zoneinfo->fNotifyLevel = DNS_ZONE_NOTIFY_LIST_ONLY;
253                 zoneinfo->dwNoRefreshInterval = serverinfo->dwDefaultNoRefreshInterval;
254                 zoneinfo->dwRefreshInterval = serverinfo->dwDefaultRefreshInterval;
255         }
256
257         zoneinfo->fReverse = fReverse;
258         zoneinfo->fPaused = 0;
259         zoneinfo->fShutdown = 0;
260         zoneinfo->fAutoCreated = 0;
261         zoneinfo->fUseDatabase = 1;
262         zoneinfo->pszDataFile = NULL;
263         zoneinfo->aipMasters = NULL;
264         zoneinfo->aipSecondaries = NULL;
265         zoneinfo->aipNotify = NULL;
266         zoneinfo->fUseWins = 0;
267         zoneinfo->fUseNbstat = 0;
268         zoneinfo->fAging = 0;
269         zoneinfo->dwAvailForScavengeTime = 0;
270         zoneinfo->aipScavengeServers = NULL;
271         zoneinfo->dwForwarderTimeout = 0;
272         zoneinfo->fForwarderSlave = 0;
273         zoneinfo->aipLocalMasters = NULL;
274         zoneinfo->pwszZoneDn = discard_const_p(char, ldb_dn_get_linearized(zone->zone_dn));
275         zoneinfo->dwLastSuccessfulSoaCheck = 0;
276         zoneinfo->dwLastSuccessfulXfr = 0;
277         zoneinfo->fQueuedForBackgroundLoad = 0;
278         zoneinfo->fBackgroundLoadInProgress = 0;
279         zoneinfo->fReadOnlyZone = 0;
280         zoneinfo->dwLastXfrAttempt = 0;
281         zoneinfo->dwLastXfrResult = 0;
282
283         return zoneinfo;
284 }
285
286 struct dnsserver_partition *dnsserver_find_partition(struct dnsserver_partition *partitions,
287                                                      const char *dp_fqdn)
288 {
289         struct dnsserver_partition *p = NULL;
290
291         for (p = partitions; p; p = p->next) {
292                 if (strcasecmp(dp_fqdn, p->pszDpFqdn) == 0) {
293                         break;
294                 }
295         }
296
297         return p;
298 }
299
300 struct dnsserver_zone *dnsserver_find_zone(struct dnsserver_zone *zones, const char *zone_name)
301 {
302         struct dnsserver_zone *z = NULL;
303
304         for (z = zones; z; z = z->next) {
305                 if (strcasecmp(zone_name, z->name) == 0) {
306                         break;
307                 }
308         }
309
310         return z;
311 }
312
313 struct ldb_dn *dnsserver_name_to_dn(TALLOC_CTX *mem_ctx, struct dnsserver_zone *z, const char *name)
314 {
315         struct ldb_dn *dn;
316         bool ret;
317
318         dn = ldb_dn_copy(mem_ctx, z->zone_dn);
319         if (dn == NULL) {
320                 return NULL;
321         }
322         if (strcasecmp(name, z->name) == 0) {
323                 ret = ldb_dn_add_child_fmt(dn, "DC=@");
324         } else {
325                 ret = ldb_dn_add_child_fmt(dn, "DC=%s", name);
326         }
327         if (!ret) {
328                 talloc_free(dn);
329                 return NULL;
330         }
331
332         return dn;
333 }
334
335 uint32_t dnsserver_zone_to_request_filter(const char *zone_name)
336 {
337         uint32_t request_filter = 0;
338
339         if (strcmp(zone_name, "..AllZones") == 0) {
340                 request_filter = DNS_ZONE_REQUEST_PRIMARY
341                         | DNS_ZONE_REQUEST_SECONDARY
342                         | DNS_ZONE_REQUEST_AUTO
343                         | DNS_ZONE_REQUEST_FORWARD
344                         | DNS_ZONE_REQUEST_REVERSE
345                         | DNS_ZONE_REQUEST_FORWARDER
346                         | DNS_ZONE_REQUEST_STUB
347                         | DNS_ZONE_REQUEST_DS
348                         | DNS_ZONE_REQUEST_NON_DS
349                         | DNS_ZONE_REQUEST_DOMAIN_DP
350                         | DNS_ZONE_REQUEST_FOREST_DP
351                         | DNS_ZONE_REQUEST_CUSTOM_DP
352                         | DNS_ZONE_REQUEST_LEGACY_DP;
353         } else if (strcmp(zone_name, "..AllZonesAndCache") == 0) {
354                 request_filter = DNS_ZONE_REQUEST_PRIMARY
355                         | DNS_ZONE_REQUEST_SECONDARY
356                         | DNS_ZONE_REQUEST_CACHE
357                         | DNS_ZONE_REQUEST_AUTO
358                         | DNS_ZONE_REQUEST_FORWARD
359                         | DNS_ZONE_REQUEST_REVERSE
360                         | DNS_ZONE_REQUEST_FORWARDER
361                         | DNS_ZONE_REQUEST_STUB
362                         | DNS_ZONE_REQUEST_DS
363                         | DNS_ZONE_REQUEST_NON_DS
364                         | DNS_ZONE_REQUEST_DOMAIN_DP
365                         | DNS_ZONE_REQUEST_FOREST_DP
366                         | DNS_ZONE_REQUEST_CUSTOM_DP
367                         | DNS_ZONE_REQUEST_LEGACY_DP;
368         } else if (strcmp(zone_name, "..AllPrimaryZones") == 0) {
369                 request_filter = DNS_ZONE_REQUEST_PRIMARY;
370         } else if (strcmp(zone_name, "..AllSecondaryZones") == 0) {
371                 request_filter = DNS_ZONE_REQUEST_SECONDARY;
372         } else if (strcmp(zone_name, "..AllForwardZones") == 0) {
373                 request_filter = DNS_ZONE_REQUEST_FORWARD;
374         } else if (strcmp(zone_name, "..AllReverseZones") == 0) {
375                 request_filter = DNS_ZONE_REQUEST_REVERSE;
376         } else if (strcmp(zone_name, "..AllDsZones") == 0) {
377                 request_filter = DNS_ZONE_REQUEST_DS;
378         } else if (strcmp(zone_name, "..AllNonDsZones") == 0) {
379                 request_filter = DNS_ZONE_REQUEST_NON_DS;
380         } else if (strcmp(zone_name, "..AllPrimaryReverseZones") == 0) {
381                 request_filter = DNS_ZONE_REQUEST_PRIMARY
382                         | DNS_ZONE_REQUEST_REVERSE;
383         } else if (strcmp(zone_name, "..AllPrimaryForwardZones") == 0) {
384                 request_filter = DNS_ZONE_REQUEST_PRIMARY
385                         | DNS_ZONE_REQUEST_FORWARD;
386         } else if (strcmp(zone_name, "..AllSecondaryReverseZones") == 0) {
387                 request_filter = DNS_ZONE_REQUEST_SECONDARY
388                         | DNS_ZONE_REQUEST_REVERSE;
389         } else if (strcmp(zone_name, "..AllSecondaryForwardZones") == 0) {
390                 request_filter = DNS_ZONE_REQUEST_SECONDARY
391                         | DNS_ZONE_REQUEST_REVERSE;
392         }
393
394         return request_filter;
395 }