s4:kdc: Implement KDC plugin hardware authentication policy
[samba.git] / source4 / dns_server / dnsserver_common.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    DNS server utils
5
6    Copyright (C) 2010 Kai Blin
7    Copyright (C) 2014 Stefan Metzmacher
8    Copyright (C) 2015 Andrew Bartlett
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "libcli/util/ntstatus.h"
26 #include "libcli/util/werror.h"
27 #include "librpc/ndr/libndr.h"
28 #include "librpc/gen_ndr/ndr_dns.h"
29 #include "librpc/gen_ndr/ndr_dnsp.h"
30 #include <ldb.h>
31 #include "dsdb/samdb/samdb.h"
32 #include "dsdb/common/util.h"
33 #include "dns_server/dnsserver_common.h"
34 #include "rpc_server/dnsserver/dnsserver.h"
35 #include "lib/util/dlinklist.h"
36 #include "system/network.h"
37
38 #undef DBGC_CLASS
39 #define DBGC_CLASS DBGC_DNS
40
41 #undef strncasecmp
42
43 uint8_t werr_to_dns_err(WERROR werr)
44 {
45         if (W_ERROR_EQUAL(WERR_OK, werr)) {
46                 return DNS_RCODE_OK;
47         } else if (W_ERROR_EQUAL(DNS_ERR(FORMAT_ERROR), werr)) {
48                 return DNS_RCODE_FORMERR;
49         } else if (W_ERROR_EQUAL(DNS_ERR(SERVER_FAILURE), werr)) {
50                 return DNS_RCODE_SERVFAIL;
51         } else if (W_ERROR_EQUAL(DNS_ERR(NAME_ERROR), werr)) {
52                 return DNS_RCODE_NXDOMAIN;
53         } else if (W_ERROR_EQUAL(WERR_DNS_ERROR_NAME_DOES_NOT_EXIST, werr)) {
54                 return DNS_RCODE_NXDOMAIN;
55         } else if (W_ERROR_EQUAL(DNS_ERR(NOT_IMPLEMENTED), werr)) {
56                 return DNS_RCODE_NOTIMP;
57         } else if (W_ERROR_EQUAL(DNS_ERR(REFUSED), werr)) {
58                 return DNS_RCODE_REFUSED;
59         } else if (W_ERROR_EQUAL(DNS_ERR(YXDOMAIN), werr)) {
60                 return DNS_RCODE_YXDOMAIN;
61         } else if (W_ERROR_EQUAL(DNS_ERR(YXRRSET), werr)) {
62                 return DNS_RCODE_YXRRSET;
63         } else if (W_ERROR_EQUAL(DNS_ERR(NXRRSET), werr)) {
64                 return DNS_RCODE_NXRRSET;
65         } else if (W_ERROR_EQUAL(DNS_ERR(NOTAUTH), werr)) {
66                 return DNS_RCODE_NOTAUTH;
67         } else if (W_ERROR_EQUAL(DNS_ERR(NOTZONE), werr)) {
68                 return DNS_RCODE_NOTZONE;
69         } else if (W_ERROR_EQUAL(DNS_ERR(BADKEY), werr)) {
70                 return DNS_RCODE_BADKEY;
71         }
72         DEBUG(5, ("No mapping exists for %s\n", win_errstr(werr)));
73         return DNS_RCODE_SERVFAIL;
74 }
75
76 WERROR dns_common_extract(struct ldb_context *samdb,
77                           const struct ldb_message_element *el,
78                           TALLOC_CTX *mem_ctx,
79                           struct dnsp_DnssrvRpcRecord **records,
80                           uint16_t *num_records)
81 {
82         uint16_t ri;
83         struct dnsp_DnssrvRpcRecord *recs;
84
85         *records = NULL;
86         *num_records = 0;
87
88         recs = talloc_zero_array(mem_ctx, struct dnsp_DnssrvRpcRecord,
89                                  el->num_values);
90         if (recs == NULL) {
91                 return WERR_NOT_ENOUGH_MEMORY;
92         }
93         for (ri = 0; ri < el->num_values; ri++) {
94                 bool am_rodc;
95                 int ret;
96                 const char *dnsHostName = NULL;
97                 struct ldb_val *v = &el->values[ri];
98                 enum ndr_err_code ndr_err;
99                 ndr_err = ndr_pull_struct_blob(v, recs, &recs[ri],
100                                 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
101                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
102                         TALLOC_FREE(recs);
103                         DEBUG(0, ("Failed to grab dnsp_DnssrvRpcRecord\n"));
104                         return DNS_ERR(SERVER_FAILURE);
105                 }
106
107                 /*
108                  * In AD, except on an RODC (where we should list a random RWDC,
109                  * we should over-stamp the MNAME with our own hostname
110                  */
111                 if (recs[ri].wType != DNS_TYPE_SOA) {
112                         continue;
113                 }
114
115                 ret = samdb_rodc(samdb, &am_rodc);
116                 if (ret != LDB_SUCCESS) {
117                         DEBUG(0, ("Failed to confirm we are not an RODC: %s\n",
118                                   ldb_errstring(samdb)));
119                         return DNS_ERR(SERVER_FAILURE);
120                 }
121
122                 if (am_rodc) {
123                         continue;
124                 }
125
126                 ret = samdb_dns_host_name(samdb, &dnsHostName);
127                 if (ret != LDB_SUCCESS || dnsHostName == NULL) {
128                         DEBUG(0, ("Failed to get dnsHostName from rootDSE\n"));
129                         return DNS_ERR(SERVER_FAILURE);
130                 }
131
132                 recs[ri].data.soa.mname = talloc_strdup(recs, dnsHostName);
133         }
134
135         *records = recs;
136         *num_records = el->num_values;
137         return WERR_OK;
138 }
139
140 /*
141  * Lookup a DNS record, performing an exact match.
142  * i.e. DNS wild card records are not considered.
143  */
144 WERROR dns_common_lookup(struct ldb_context *samdb,
145                          TALLOC_CTX *mem_ctx,
146                          struct ldb_dn *dn,
147                          struct dnsp_DnssrvRpcRecord **records,
148                          uint16_t *num_records,
149                          bool *tombstoned)
150 {
151         const struct timeval start = timeval_current();
152         static const char * const attrs[] = {
153                 "dnsRecord",
154                 "dNSTombstoned",
155                 NULL
156         };
157         int ret;
158         WERROR werr = WERR_OK;
159         struct ldb_message *msg = NULL;
160         struct ldb_message_element *el;
161
162         *records = NULL;
163         *num_records = 0;
164
165         if (tombstoned != NULL) {
166                 *tombstoned = false;
167                 ret = dsdb_search_one(samdb, mem_ctx, &msg, dn,
168                         LDB_SCOPE_BASE, attrs, 0,
169                         "(objectClass=dnsNode)");
170         } else {
171                 ret = dsdb_search_one(samdb, mem_ctx, &msg, dn,
172                         LDB_SCOPE_BASE, attrs, 0,
173                         "(&(objectClass=dnsNode)(!(dNSTombstoned=TRUE)))");
174         }
175         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
176                 werr = WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
177                 goto exit;
178         }
179         if (ret != LDB_SUCCESS) {
180                 /* TODO: we need to check if there's a glue record we need to
181                  * create a referral to */
182                 werr = DNS_ERR(NAME_ERROR);
183                 goto exit;
184         }
185
186         if (tombstoned != NULL) {
187                 *tombstoned = ldb_msg_find_attr_as_bool(msg,
188                                         "dNSTombstoned", false);
189         }
190
191         el = ldb_msg_find_element(msg, "dnsRecord");
192         if (el == NULL) {
193                 TALLOC_FREE(msg);
194                 /*
195                  * records produced by older Samba releases
196                  * keep dnsNode objects without dnsRecord and
197                  * without setting dNSTombstoned=TRUE.
198                  *
199                  * We just pretend they're tombstones.
200                  */
201                 if (tombstoned != NULL) {
202                         struct dnsp_DnssrvRpcRecord *recs;
203                         recs = talloc_array(mem_ctx,
204                                             struct dnsp_DnssrvRpcRecord,
205                                             1);
206                         if (recs == NULL) {
207                                 werr = WERR_NOT_ENOUGH_MEMORY;
208                                 goto exit;
209                         }
210                         recs[0] = (struct dnsp_DnssrvRpcRecord) {
211                                 .wType = DNS_TYPE_TOMBSTONE,
212                                 /*
213                                  * A value of timestamp != 0
214                                  * indicated that the object was already
215                                  * a tombstone, this will be used
216                                  * in dns_common_replace()
217                                  */
218                                 .data.EntombedTime = 1,
219                         };
220
221                         *tombstoned = true;
222                         *records = recs;
223                         *num_records = 1;
224                         werr = WERR_OK;
225                         goto exit;
226                 } else {
227                         /*
228                          * Because we are not looking for a tombstone
229                          * in this codepath, we just pretend it does
230                          * not exist at all.
231                          */
232                         werr = WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
233                         goto exit;
234                 }
235         }
236
237         werr = dns_common_extract(samdb, el, mem_ctx, records, num_records);
238         TALLOC_FREE(msg);
239         if (!W_ERROR_IS_OK(werr)) {
240                 goto exit;
241         }
242
243         werr = WERR_OK;
244 exit:
245         DNS_COMMON_LOG_OPERATION(
246                 win_errstr(werr),
247                 &start,
248                 NULL,
249                 dn == NULL ? NULL : ldb_dn_get_linearized(dn),
250                 NULL);
251         return werr;
252 }
253
254 /*
255  * Build an ldb_parse_tree node for an equality check
256  *
257  * Note: name is assumed to have been validated by dns_name_check
258  *       so will be zero terminated and of a reasonable size.
259  */
260 static struct ldb_parse_tree *build_equality_operation(
261         TALLOC_CTX *mem_ctx,
262         bool add_asterix,     /* prepend an '*' to the name          */
263         const uint8_t *name,  /* the value being matched             */
264         const char *attr,     /* the attribute to check name against */
265         size_t size)          /* length of name                      */
266 {
267
268         struct ldb_parse_tree *el = NULL;  /* Equality node being built */
269         struct ldb_val *value = NULL;      /* Value the attr will be compared
270                                               with */
271         size_t length = 0;                 /* calculated length of the value
272                                               including option '*' prefix and
273                                               '\0' string terminator */
274
275         el = talloc(mem_ctx, struct ldb_parse_tree);
276         if (el == NULL) {
277                 DBG_ERR("Unable to allocate ldb_parse_tree\n");
278                 return NULL;
279         }
280
281         el->operation = LDB_OP_EQUALITY;
282         el->u.equality.attr = talloc_strdup(mem_ctx, attr);
283         value = &el->u.equality.value;
284         length = (add_asterix) ? size + 2 : size + 1;
285         value->data = talloc_zero_array(el, uint8_t, length);
286         if (value->data == NULL) {
287                 DBG_ERR("Unable to allocate value->data\n");
288                 TALLOC_FREE(el);
289                 return NULL;
290         }
291
292         value->length = length;
293         if (add_asterix) {
294                 value->data[0] = '*';
295                 if (name != NULL) {
296                         memcpy(&value->data[1], name, size);
297                 }
298         } else if (name != NULL) {
299                 memcpy(value->data, name, size);
300         }
301         return el;
302 }
303
304 /*
305  * Determine the number of levels in name
306  * essentially the number of '.'s in the name + 1
307  *
308  * name is assumed to have been validated by dns_name_check
309  */
310 static unsigned int number_of_labels(const struct ldb_val *name) {
311         int x  = 0;
312         unsigned int labels = 1;
313         for (x = 0; x < name->length; x++) {
314                 if (name->data[x] == '.') {
315                         labels++;
316                 }
317         }
318         return labels;
319 }
320 /*
321  * Build a query that matches the target name, and any possible
322  * DNS wild card entries
323  *
324  * Builds a parse tree equivalent to the example query.
325  *
326  * x.y.z -> (|(name=x.y.z)(name=\2a.y.z)(name=\2a.z)(name=\2a))
327  *
328  * The attribute 'name' is used as this is what the LDB index is on
329  * (the RDN, being 'dc' in this use case, does not have an index in
330  * the AD schema).
331  *
332  * Returns NULL if unable to build the query.
333  *
334  * The first component of the DN is assumed to be the name being looked up
335  * and also that it has been validated by dns_name_check
336  *
337  */
338 #define BASE "(&(objectClass=dnsNode)(!(dNSTombstoned=TRUE))(|(a=b)(c=d)))"
339 static struct ldb_parse_tree *build_wildcard_query(
340         TALLOC_CTX *mem_ctx,
341         struct ldb_dn *dn)
342 {
343         const struct ldb_val *name = NULL;            /* The DNS name being
344                                                          queried */
345         const char *attr = "name";                    /* The attribute name */
346         struct ldb_parse_tree *query = NULL;          /* The constructed query
347                                                          parse tree*/
348         struct ldb_parse_tree *wildcard_query = NULL; /* The parse tree for the
349                                                          name and wild card
350                                                          entries */
351         int labels = 0;         /* The number of labels in the name */
352
353         name = ldb_dn_get_rdn_val(dn);
354         if (name == NULL) {
355                 DBG_ERR("Unable to get domain name value\n");
356                 return NULL;
357         }
358         labels = number_of_labels(name);
359
360         query = ldb_parse_tree(mem_ctx, BASE);
361         if (query == NULL) {
362                 DBG_ERR("Unable to parse query %s\n", BASE);
363                 return NULL;
364         }
365
366         /*
367          * The 3rd element of BASE is a place holder which is replaced with
368          * the actual wild card query
369          */
370         wildcard_query = query->u.list.elements[2];
371         TALLOC_FREE(wildcard_query->u.list.elements);
372
373         wildcard_query->u.list.num_elements = labels + 1;
374         wildcard_query->u.list.elements = talloc_array(
375                 wildcard_query,
376                 struct ldb_parse_tree *,
377                 labels + 1);
378         /*
379          * Build the wild card query
380          */
381         {
382                 int x = 0;   /* current character in the name               */
383                 int l = 0;   /* current equality operator index in elements */
384                 struct ldb_parse_tree *el = NULL; /* Equality operator being
385                                                      built */
386                 bool add_asterix = true;  /* prepend an '*' to the value    */
387                 for (l = 0, x = 0; l < labels && x < name->length; l++) {
388                         unsigned int size = name->length - x;
389                         add_asterix = (name->data[x] == '.');
390                         el = build_equality_operation(
391                                 mem_ctx,
392                                 add_asterix,
393                                 &name->data[x],
394                                 attr,
395                                 size);
396                         if (el == NULL) {
397                                 return NULL;  /* Reason will have been logged */
398                         }
399                         wildcard_query->u.list.elements[l] = el;
400
401                         /* skip to the start of the next label */
402                         x++;
403                         for (;x < name->length && name->data[x] != '.'; x++);
404                 }
405
406                 /* Add the base level "*" only query */
407                 el = build_equality_operation(mem_ctx, true, NULL, attr, 0);
408                 if (el == NULL) {
409                         TALLOC_FREE(query);
410                         return NULL;  /* Reason will have been logged */
411                 }
412                 wildcard_query->u.list.elements[l] = el;
413         }
414         return query;
415 }
416
417 /*
418  * Scan the list of records matching a dns wildcard query and return the
419  * best match.
420  *
421  * The best match is either an exact name match, or the longest wild card
422  * entry returned
423  *
424  * i.e. name = a.b.c candidates *.b.c, *.c,        - *.b.c would be selected
425  *      name = a.b.c candidates a.b.c, *.b.c, *.c  - a.b.c would be selected
426  */
427 static struct ldb_message *get_best_match(struct ldb_dn *dn,
428                                           struct ldb_result *result)
429 {
430         int matched = 0;    /* Index of the current best match in result */
431         size_t length = 0;  /* The length of the current candidate       */
432         const struct ldb_val *target = NULL;    /* value we're looking for */
433         const struct ldb_val *candidate = NULL; /* current candidate value */
434         int x = 0;
435
436         target = ldb_dn_get_rdn_val(dn);
437         for(x = 0; x < result->count; x++) {
438                 candidate = ldb_dn_get_rdn_val(result->msgs[x]->dn);
439                 if (strncasecmp((char *) target->data,
440                                 (char *) candidate->data,
441                                 target->length) == 0) {
442                         /* Exact match stop searching and return */
443                         return result->msgs[x];
444                 }
445                 if (candidate->length > length) {
446                         matched = x;
447                         length  = candidate->length;
448                 }
449         }
450         return result->msgs[matched];
451 }
452
453 /*
454  * Look up a DNS entry, if an exact match does not exist, return the
455  * closest matching DNS wildcard entry if available
456  *
457  * Returns: LDB_ERR_NO_SUCH_OBJECT     If no matching record exists
458  *          LDB_ERR_OPERATIONS_ERROR   If the query fails
459  *          LDB_SUCCESS                If a matching record was retrieved
460  *
461  */
462 static int dns_wildcard_lookup(struct ldb_context *samdb,
463                                TALLOC_CTX *mem_ctx,
464                                struct ldb_dn *dn,
465                                struct ldb_message **msg)
466 {
467         static const char * const attrs[] = {
468                 "dnsRecord",
469                 "dNSTombstoned",
470                 NULL
471         };
472         struct ldb_dn *parent = NULL;     /* The parent dn                    */
473         struct ldb_result *result = NULL; /* Results of the search            */
474         int ret;                          /* Return code                      */
475         struct ldb_parse_tree *query = NULL; /* The query to run              */
476         struct ldb_request *request = NULL;  /* LDB request for the query op  */
477         struct ldb_message *match = NULL;    /* the best matching DNS record  */
478         TALLOC_CTX *frame = talloc_stackframe();
479
480         parent = ldb_dn_get_parent(frame, dn);
481         if (parent == NULL) {
482                 DBG_ERR("Unable to extract parent from dn\n");
483                 TALLOC_FREE(frame);
484                 return LDB_ERR_OPERATIONS_ERROR;
485         }
486
487         query = build_wildcard_query(frame, dn);
488         if (query == NULL) {
489                 TALLOC_FREE(frame);
490                 return LDB_ERR_OPERATIONS_ERROR;
491         }
492
493         result = talloc_zero(mem_ctx, struct ldb_result);
494         if (result == NULL) {
495                 TALLOC_FREE(frame);
496                 DBG_ERR("Unable to allocate ldb_result\n");
497                 return LDB_ERR_OPERATIONS_ERROR;
498         }
499
500         ret = ldb_build_search_req_ex(&request,
501                                       samdb,
502                                       frame,
503                                       parent,
504                                       LDB_SCOPE_SUBTREE,
505                                       query,
506                                       attrs,
507                                       NULL,
508                                       result,
509                                       ldb_search_default_callback,
510                                       NULL);
511         if (ret != LDB_SUCCESS) {
512                 TALLOC_FREE(frame);
513                 DBG_ERR("ldb_build_search_req_ex returned %d\n", ret);
514                 return ret;
515         }
516
517         ret = ldb_request(samdb, request);
518         if (ret != LDB_SUCCESS) {
519                 TALLOC_FREE(frame);
520                 return ret;
521         }
522
523         ret = ldb_wait(request->handle, LDB_WAIT_ALL);
524         if (ret != LDB_SUCCESS) {
525                 TALLOC_FREE(frame);
526                 return ret;
527         }
528
529         if (result->count == 0) {
530                 TALLOC_FREE(frame);
531                 return LDB_ERR_NO_SUCH_OBJECT;
532         }
533
534         match = get_best_match(dn, result);
535         if (match == NULL) {
536                 TALLOC_FREE(frame);
537                 return LDB_ERR_OPERATIONS_ERROR;
538         }
539
540         *msg = talloc_move(mem_ctx, &match);
541         TALLOC_FREE(frame);
542         return LDB_SUCCESS;
543 }
544
545 /*
546  * Lookup a DNS record, will match DNS wild card records if an exact match
547  * is not found.
548  */
549 WERROR dns_common_wildcard_lookup(struct ldb_context *samdb,
550                                   TALLOC_CTX *mem_ctx,
551                                   struct ldb_dn *dn,
552                                   struct dnsp_DnssrvRpcRecord **records,
553                                   uint16_t *num_records)
554 {
555         const struct timeval start = timeval_current();
556         int ret;
557         WERROR werr = WERR_OK;
558         struct ldb_message *msg = NULL;
559         struct ldb_message_element *el = NULL;
560         const struct ldb_val *name = NULL;
561
562         *records = NULL;
563         *num_records = 0;
564
565         name = ldb_dn_get_rdn_val(dn);
566         if (name == NULL) {
567                 werr = DNS_ERR(NAME_ERROR);
568                 goto exit;
569         }
570
571         /* Don't look for a wildcard for @ */
572         if (name->length == 1 && name->data[0] == '@') {
573                 werr = dns_common_lookup(samdb,
574                                          mem_ctx,
575                                          dn,
576                                          records,
577                                          num_records,
578                                          NULL);
579                 goto exit;
580         }
581
582         werr =  dns_name_check(
583                         mem_ctx,
584                         strlen((const char*)name->data),
585                         (const char*) name->data);
586         if (!W_ERROR_IS_OK(werr)) {
587                 goto exit;
588         }
589
590         /*
591          * Do a point search first, then fall back to a wildcard
592          * lookup if it does not exist
593          */
594         werr = dns_common_lookup(samdb,
595                                  mem_ctx,
596                                  dn,
597                                  records,
598                                  num_records,
599                                  NULL);
600         if (!W_ERROR_EQUAL(werr, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) {
601                 goto exit;
602         }
603
604         ret = dns_wildcard_lookup(samdb, mem_ctx, dn, &msg);
605         if (ret == LDB_ERR_OPERATIONS_ERROR) {
606                 werr = DNS_ERR(SERVER_FAILURE);
607                 goto exit;
608         }
609         if (ret != LDB_SUCCESS) {
610                 werr = DNS_ERR(NAME_ERROR);
611                 goto exit;
612         }
613
614         el = ldb_msg_find_element(msg, "dnsRecord");
615         if (el == NULL) {
616                 werr = WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
617                 goto exit;
618         }
619
620         werr = dns_common_extract(samdb, el, mem_ctx, records, num_records);
621         TALLOC_FREE(msg);
622         if (!W_ERROR_IS_OK(werr)) {
623                 goto exit;
624         }
625
626         werr = WERR_OK;
627 exit:
628         DNS_COMMON_LOG_OPERATION(
629                 win_errstr(werr),
630                 &start,
631                 NULL,
632                 dn == NULL ? NULL : ldb_dn_get_linearized(dn),
633                 NULL);
634         return werr;
635 }
636
637 static int rec_cmp(const struct dnsp_DnssrvRpcRecord *r1,
638                    const struct dnsp_DnssrvRpcRecord *r2)
639 {
640         if (r1->wType != r2->wType) {
641                 /*
642                  * The records are sorted with higher types first,
643                  * which puts tombstones (type 0) last.
644                  */
645                 return NUMERIC_CMP(r2->wType, r1->wType);
646         }
647         /*
648          * Then we need to sort from the oldest to newest timestamp.
649          *
650          * Note that dwTimeStamp == 0 (never expiring) records come first,
651          * then the ones whose expiry is soonest.
652          */
653         return NUMERIC_CMP(r1->dwTimeStamp, r2->dwTimeStamp);
654 }
655
656 /*
657  * Check for valid DNS names. These are names which:
658  *   - are non-empty
659  *   - do not start with a dot
660  *   - do not have any empty labels
661  *   - have no more than 127 labels
662  *   - are no longer than 253 characters
663  *   - none of the labels exceed 63 characters
664  */
665 WERROR dns_name_check(TALLOC_CTX *mem_ctx, size_t len, const char *name)
666 {
667         size_t i;
668         unsigned int labels    = 0;
669         unsigned int label_len = 0;
670
671         if (len == 0) {
672                 return WERR_DS_INVALID_DN_SYNTAX;
673         }
674
675         if (len > 1 && name[0] == '.') {
676                 return WERR_DS_INVALID_DN_SYNTAX;
677         }
678
679         if ((len - 1) > DNS_MAX_DOMAIN_LENGTH) {
680                 return WERR_DS_INVALID_DN_SYNTAX;
681         }
682
683         for (i = 0; i < len - 1; i++) {
684                 if (name[i] == '.' && name[i+1] == '.') {
685                         return WERR_DS_INVALID_DN_SYNTAX;
686                 }
687                 if (name[i] == '.') {
688                         labels++;
689                         if (labels > DNS_MAX_LABELS) {
690                                 return WERR_DS_INVALID_DN_SYNTAX;
691                         }
692                         label_len = 0;
693                 } else {
694                         label_len++;
695                         if (label_len > DNS_MAX_LABEL_LENGTH) {
696                                 return WERR_DS_INVALID_DN_SYNTAX;
697                         }
698                 }
699         }
700
701         return WERR_OK;
702 }
703
704 static WERROR check_name_list(TALLOC_CTX *mem_ctx, uint16_t rec_count,
705                               struct dnsp_DnssrvRpcRecord *records)
706 {
707         WERROR werr;
708         uint16_t i;
709         size_t len;
710         struct dnsp_DnssrvRpcRecord record;
711
712         werr = WERR_OK;
713         for (i = 0; i < rec_count; i++) {
714                 record = records[i];
715
716                 switch (record.wType) {
717
718                 case DNS_TYPE_NS:
719                         len = strlen(record.data.ns);
720                         werr = dns_name_check(mem_ctx, len, record.data.ns);
721                         break;
722                 case DNS_TYPE_CNAME:
723                         len = strlen(record.data.cname);
724                         werr = dns_name_check(mem_ctx, len, record.data.cname);
725                         break;
726                 case DNS_TYPE_SOA:
727                         len = strlen(record.data.soa.mname);
728                         werr = dns_name_check(mem_ctx, len, record.data.soa.mname);
729                         if (!W_ERROR_IS_OK(werr)) {
730                                 break;
731                         }
732                         len = strlen(record.data.soa.rname);
733                         werr = dns_name_check(mem_ctx, len, record.data.soa.rname);
734                         break;
735                 case DNS_TYPE_PTR:
736                         len = strlen(record.data.ptr);
737                         werr = dns_name_check(mem_ctx, len, record.data.ptr);
738                         break;
739                 case DNS_TYPE_MX:
740                         len = strlen(record.data.mx.nameTarget);
741                         werr = dns_name_check(mem_ctx, len, record.data.mx.nameTarget);
742                         break;
743                 case DNS_TYPE_SRV:
744                         len = strlen(record.data.srv.nameTarget);
745                         werr = dns_name_check(mem_ctx, len,
746                                               record.data.srv.nameTarget);
747                         break;
748                 /*
749                  * In the default case, the record doesn't have a DN, so it
750                  * must be ok.
751                  */
752                 default:
753                         break;
754                 }
755
756                 if (!W_ERROR_IS_OK(werr)) {
757                         return werr;
758                 }
759         }
760
761         return WERR_OK;
762 }
763
764 bool dns_name_is_static(struct dnsp_DnssrvRpcRecord *records,
765                         uint16_t rec_count)
766 {
767         int i = 0;
768         for (i = 0; i < rec_count; i++) {
769                 if (records[i].wType == DNS_TYPE_TOMBSTONE) {
770                         continue;
771                 }
772
773                 if (records[i].wType == DNS_TYPE_SOA ||
774                     records[i].dwTimeStamp == 0) {
775                         return true;
776                 }
777         }
778         return false;
779 }
780
781 /*
782  * Helper function to copy a dnsp_ip4_array struct to an IP4_ARRAY struct.
783  * The new structure and it's data are allocated on the supplied talloc context
784  */
785 static struct IP4_ARRAY *copy_ip4_array(TALLOC_CTX *ctx,
786                                         const char *name,
787                                         struct dnsp_ip4_array array)
788 {
789
790         struct IP4_ARRAY *ip4_array = NULL;
791         unsigned int i;
792
793         ip4_array = talloc_zero(ctx, struct IP4_ARRAY);
794         if (ip4_array == NULL) {
795                 DBG_ERR("Out of memory copying property [%s]\n", name);
796                 return NULL;
797         }
798
799         ip4_array->AddrCount = array.addrCount;
800         if (ip4_array->AddrCount == 0) {
801                 return ip4_array;
802         }
803
804         ip4_array->AddrArray =
805             talloc_array(ip4_array, uint32_t, ip4_array->AddrCount);
806         if (ip4_array->AddrArray == NULL) {
807                 TALLOC_FREE(ip4_array);
808                 DBG_ERR("Out of memory copying property [%s] values\n", name);
809                 return NULL;
810         }
811
812         for (i = 0; i < ip4_array->AddrCount; i++) {
813                 ip4_array->AddrArray[i] = array.addrArray[i];
814         }
815
816         return ip4_array;
817 }
818
819 bool dns_zoneinfo_load_zone_property(struct dnsserver_zoneinfo *zoneinfo,
820                                      struct dnsp_DnsProperty *prop)
821 {
822         switch (prop->id) {
823         case DSPROPERTY_ZONE_TYPE:
824                 zoneinfo->dwZoneType = prop->data.zone_type;
825                 break;
826         case DSPROPERTY_ZONE_ALLOW_UPDATE:
827                 zoneinfo->fAllowUpdate = prop->data.allow_update_flag;
828                 break;
829         case DSPROPERTY_ZONE_NOREFRESH_INTERVAL:
830                 zoneinfo->dwNoRefreshInterval = prop->data.norefresh_hours;
831                 break;
832         case DSPROPERTY_ZONE_REFRESH_INTERVAL:
833                 zoneinfo->dwRefreshInterval = prop->data.refresh_hours;
834                 break;
835         case DSPROPERTY_ZONE_AGING_STATE:
836                 zoneinfo->fAging = prop->data.aging_enabled;
837                 break;
838         case DSPROPERTY_ZONE_SCAVENGING_SERVERS:
839                 zoneinfo->aipScavengeServers = copy_ip4_array(
840                     zoneinfo, "ZONE_SCAVENGING_SERVERS", prop->data.servers);
841                 if (zoneinfo->aipScavengeServers == NULL) {
842                         return false;
843                 }
844                 break;
845         case DSPROPERTY_ZONE_AGING_ENABLED_TIME:
846                 zoneinfo->dwAvailForScavengeTime =
847                     prop->data.next_scavenging_cycle_hours;
848                 break;
849         case DSPROPERTY_ZONE_MASTER_SERVERS:
850                 zoneinfo->aipLocalMasters = copy_ip4_array(
851                     zoneinfo, "ZONE_MASTER_SERVERS", prop->data.master_servers);
852                 if (zoneinfo->aipLocalMasters == NULL) {
853                         return false;
854                 }
855                 break;
856         case DSPROPERTY_ZONE_EMPTY:
857         case DSPROPERTY_ZONE_SECURE_TIME:
858         case DSPROPERTY_ZONE_DELETED_FROM_HOSTNAME:
859         case DSPROPERTY_ZONE_AUTO_NS_SERVERS:
860         case DSPROPERTY_ZONE_DCPROMO_CONVERT:
861         case DSPROPERTY_ZONE_SCAVENGING_SERVERS_DA:
862         case DSPROPERTY_ZONE_MASTER_SERVERS_DA:
863         case DSPROPERTY_ZONE_NS_SERVERS_DA:
864         case DSPROPERTY_ZONE_NODE_DBFLAGS:
865                 break;
866         }
867         return true;
868 }
869 WERROR dns_get_zone_properties(struct ldb_context *samdb,
870                                TALLOC_CTX *mem_ctx,
871                                struct ldb_dn *zone_dn,
872                                struct dnsserver_zoneinfo *zoneinfo)
873 {
874
875         int ret, i;
876         struct dnsp_DnsProperty *prop = NULL;
877         struct ldb_message_element *element = NULL;
878         const char *const attrs[] = {"dNSProperty", NULL};
879         struct ldb_result *res = NULL;
880         enum ndr_err_code err;
881
882         ret = ldb_search(samdb,
883                          mem_ctx,
884                          &res,
885                          zone_dn,
886                          LDB_SCOPE_BASE,
887                          attrs,
888                          "(objectClass=dnsZone)");
889         if (ret != LDB_SUCCESS) {
890                 DBG_ERR("dnsserver: Failed to find DNS zone: %s\n",
891                         ldb_dn_get_linearized(zone_dn));
892                 return DNS_ERR(SERVER_FAILURE);
893         }
894
895         element = ldb_msg_find_element(res->msgs[0], "dNSProperty");
896         if (element == NULL) {
897                 return DNS_ERR(NOTZONE);
898         }
899
900         for (i = 0; i < element->num_values; i++) {
901                 bool valid_property;
902                 prop = talloc_zero(mem_ctx, struct dnsp_DnsProperty);
903                 if (prop == NULL) {
904                         return WERR_NOT_ENOUGH_MEMORY;
905                 }
906                 err = ndr_pull_struct_blob(
907                     &(element->values[i]),
908                     mem_ctx,
909                     prop,
910                     (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty);
911                 if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
912                         /*
913                          * If we can't pull it, then there is no valid
914                          * data to load into the zone, so ignore this
915                          * as Microsoft does.  Windows can load an
916                          * invalid property with a zero length into
917                          * the dnsProperty attribute.
918                          */
919                         continue;
920                 }
921
922                 valid_property =
923                     dns_zoneinfo_load_zone_property(zoneinfo, prop);
924                 if (!valid_property) {
925                         return DNS_ERR(SERVER_FAILURE);
926                 }
927         }
928
929         return WERR_OK;
930 }
931
932 WERROR dns_common_replace(struct ldb_context *samdb,
933                           TALLOC_CTX *mem_ctx,
934                           struct ldb_dn *dn,
935                           bool needs_add,
936                           uint32_t serial,
937                           struct dnsp_DnssrvRpcRecord *records,
938                           uint16_t rec_count)
939 {
940         const struct timeval start = timeval_current();
941         struct ldb_message_element *el;
942         uint16_t i;
943         int ret;
944         WERROR werr;
945         struct ldb_message *msg = NULL;
946         bool was_tombstoned = false;
947         bool become_tombstoned = false;
948         struct ldb_dn *zone_dn = NULL;
949         struct dnsserver_zoneinfo *zoneinfo = NULL;
950         uint32_t t;
951
952         msg = ldb_msg_new(mem_ctx);
953         W_ERROR_HAVE_NO_MEMORY(msg);
954
955         msg->dn = dn;
956
957         zone_dn = ldb_dn_copy(mem_ctx, dn);
958         if (zone_dn == NULL) {
959                 werr = WERR_NOT_ENOUGH_MEMORY;
960                 goto exit;
961         }
962         if (!ldb_dn_remove_child_components(zone_dn, 1)) {
963                 werr = DNS_ERR(SERVER_FAILURE);
964                 goto exit;
965         }
966         zoneinfo = talloc(mem_ctx, struct dnsserver_zoneinfo);
967         if (zoneinfo == NULL) {
968                 werr = WERR_NOT_ENOUGH_MEMORY;
969                 goto exit;
970         }
971         werr = dns_get_zone_properties(samdb, mem_ctx, zone_dn, zoneinfo);
972         if (W_ERROR_EQUAL(DNS_ERR(NOTZONE), werr)) {
973                 /*
974                  * We only got zoneinfo for aging so if we didn't find any
975                  * properties then just disable aging and keep going.
976                  */
977                 zoneinfo->fAging = 0;
978         } else if (!W_ERROR_IS_OK(werr)) {
979                 goto exit;
980         }
981
982         werr = check_name_list(mem_ctx, rec_count, records);
983         if (!W_ERROR_IS_OK(werr)) {
984                 goto exit;
985         }
986
987         ret = ldb_msg_add_empty(msg, "dnsRecord", LDB_FLAG_MOD_REPLACE, &el);
988         if (ret != LDB_SUCCESS) {
989                 werr = DNS_ERR(SERVER_FAILURE);
990                 goto exit;
991         }
992
993         /*
994          * we have at least one value,
995          * which might be used for the tombstone marker
996          */
997         el->values = talloc_zero_array(el, struct ldb_val, MAX(1, rec_count));
998         if (el->values == NULL) {
999                 werr = WERR_NOT_ENOUGH_MEMORY;
1000                 goto exit;
1001         }
1002
1003         if (rec_count > 1) {
1004                 /*
1005                  * We store a sorted list with the high wType values first
1006                  * that's what windows does. It also simplifies the
1007                  * filtering of DNS_TYPE_TOMBSTONE records
1008                  */
1009                 TYPESAFE_QSORT(records, rec_count, rec_cmp);
1010         }
1011
1012         for (i = 0; i < rec_count; i++) {
1013                 struct ldb_val *v = &el->values[el->num_values];
1014                 enum ndr_err_code ndr_err;
1015
1016                 if (records[i].wType == DNS_TYPE_TOMBSTONE) {
1017                         /*
1018                          * There are two things that could be going on here.
1019                          *
1020                          * 1. We use a tombstone with EntombedTime == 0 for
1021                          * passing deletion messages through the stack, and
1022                          * this is the place we filter them out to perform
1023                          * that deletion.
1024                          *
1025                          * 2. This node is tombstoned, with no records except
1026                          * for a single tombstone, and it is just waiting to
1027                          * disappear. In this case, unless the caller has
1028                          * added a record, rec_count should be 1, and
1029                          * el->num_values will end up at 0, and we will make
1030                          * no changes. But if the caller has added a record,
1031                          * we need to un-tombstone the node.
1032                          *
1033                          * It is not possible to add an explicit tombstone
1034                          * record.
1035                          */
1036                         if (records[i].data.EntombedTime != 0) {
1037                                 if (rec_count != 1 && DEBUGLVL(DBGLVL_NOTICE)) {
1038                                         DBG_NOTICE("tombstone record [%u] has "
1039                                                    "%u neighbour records.\n",
1040                                                    i, rec_count - 1);
1041                                         NDR_PRINT_DEBUG(dnsp_DnssrvRpcRecord, &records[i]);
1042                                 }
1043                                 was_tombstoned = true;
1044                         }
1045                         continue;
1046                 }
1047
1048                 if (zoneinfo->fAging == 1 && records[i].dwTimeStamp != 0) {
1049                         t = unix_to_dns_timestamp(time(NULL));
1050                         if (t - records[i].dwTimeStamp >
1051                             zoneinfo->dwNoRefreshInterval) {
1052                                 records[i].dwTimeStamp = t;
1053                         }
1054                 }
1055
1056                 records[i].dwSerial = serial;
1057                 ndr_err = ndr_push_struct_blob(v, el->values, &records[i],
1058                                 (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord);
1059                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1060                         DEBUG(0, ("Failed to push dnsp_DnssrvRpcRecord\n"));
1061                         werr = DNS_ERR(SERVER_FAILURE);
1062                         goto exit;
1063                 }
1064                 el->num_values++;
1065         }
1066
1067         if (needs_add) {
1068                 /*
1069                  * This is a new dnsNode, which simplifies everything as we
1070                  * know there is nothing to delete or change. We add the
1071                  * records and get out.
1072                  */
1073                 if (el->num_values == 0) {
1074                         werr = WERR_OK;
1075                         goto exit;
1076                 }
1077
1078                 ret = ldb_msg_add_string(msg, "objectClass", "dnsNode");
1079                 if (ret != LDB_SUCCESS) {
1080                         werr = DNS_ERR(SERVER_FAILURE);
1081                         goto exit;
1082                 }
1083
1084                 ret = ldb_add(samdb, msg);
1085                 if (ret != LDB_SUCCESS) {
1086                         werr = DNS_ERR(SERVER_FAILURE);
1087                         goto exit;
1088                 }
1089
1090                 werr = WERR_OK;
1091                 goto exit;
1092         }
1093
1094         if (el->num_values == 0) {
1095                 /*
1096                  * We get here if there are no records or all the records were
1097                  * tombstones.
1098                  */
1099                 struct dnsp_DnssrvRpcRecord tbs;
1100                 struct ldb_val *v = &el->values[el->num_values];
1101                 enum ndr_err_code ndr_err;
1102                 struct timeval tv;
1103
1104                 if (was_tombstoned) {
1105                         /*
1106                          * This is already a tombstoned object.
1107                          * Just leave it instead of updating the time stamp.
1108                          */
1109                         werr = WERR_OK;
1110                         goto exit;
1111                 }
1112
1113                 tv = timeval_current();
1114                 tbs = (struct dnsp_DnssrvRpcRecord) {
1115                         .wType = DNS_TYPE_TOMBSTONE,
1116                         .dwSerial = serial,
1117                         .data.EntombedTime = timeval_to_nttime(&tv),
1118                 };
1119
1120                 ndr_err = ndr_push_struct_blob(v, el->values, &tbs,
1121                                 (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord);
1122                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1123                         DEBUG(0, ("Failed to push dnsp_DnssrvRpcRecord\n"));
1124                         werr = DNS_ERR(SERVER_FAILURE);
1125                         goto exit;
1126                 }
1127                 el->num_values++;
1128
1129                 become_tombstoned = true;
1130         }
1131
1132         if (was_tombstoned || become_tombstoned) {
1133                 ret = ldb_msg_append_fmt(msg, LDB_FLAG_MOD_REPLACE,
1134                                          "dNSTombstoned", "%s",
1135                                          become_tombstoned ? "TRUE" : "FALSE");
1136                 if (ret != LDB_SUCCESS) {
1137                         werr = DNS_ERR(SERVER_FAILURE);
1138                         goto exit;
1139                 }
1140         }
1141
1142         ret = ldb_modify(samdb, msg);
1143         if (ret != LDB_SUCCESS) {
1144                 NTSTATUS nt = dsdb_ldb_err_to_ntstatus(ret);
1145                 werr = ntstatus_to_werror(nt);
1146                 goto exit;
1147         }
1148
1149         werr = WERR_OK;
1150 exit:
1151         talloc_free(msg);
1152         DNS_COMMON_LOG_OPERATION(
1153                 win_errstr(werr),
1154                 &start,
1155                 NULL,
1156                 dn == NULL ? NULL : ldb_dn_get_linearized(dn),
1157                 NULL);
1158         return werr;
1159 }
1160
1161 bool dns_name_match(const char *zone, const char *name, size_t *host_part_len)
1162 {
1163         size_t zl = strlen(zone);
1164         size_t nl = strlen(name);
1165         ssize_t zi, ni;
1166         static const size_t fixup = 'a' - 'A';
1167
1168         if (zl > nl) {
1169                 return false;
1170         }
1171
1172         for (zi = zl, ni = nl; zi >= 0; zi--, ni--) {
1173                 char zc = zone[zi];
1174                 char nc = name[ni];
1175
1176                 /* convert to lower case */
1177                 if (zc >= 'A' && zc <= 'Z') {
1178                         zc += fixup;
1179                 }
1180                 if (nc >= 'A' && nc <= 'Z') {
1181                         nc += fixup;
1182                 }
1183
1184                 if (zc != nc) {
1185                         return false;
1186                 }
1187         }
1188
1189         if (ni >= 0) {
1190                 if (name[ni] != '.') {
1191                         return false;
1192                 }
1193
1194                 ni--;
1195         }
1196
1197         *host_part_len = ni+1;
1198
1199         return true;
1200 }
1201
1202 WERROR dns_common_name2dn(struct ldb_context *samdb,
1203                           struct dns_server_zone *zones,
1204                           TALLOC_CTX *mem_ctx,
1205                           const char *name,
1206                           struct ldb_dn **_dn)
1207 {
1208         struct ldb_dn *base;
1209         struct ldb_dn *dn;
1210         const struct dns_server_zone *z;
1211         size_t host_part_len = 0;
1212         struct ldb_val host_part;
1213         WERROR werr;
1214         bool ok;
1215         const char *casefold = NULL;
1216
1217         if (name == NULL) {
1218                 return DNS_ERR(FORMAT_ERROR);
1219         }
1220
1221         if (strcmp(name, "") == 0) {
1222                 base = ldb_get_default_basedn(samdb);
1223                 dn = ldb_dn_copy(mem_ctx, base);
1224                 ok = ldb_dn_add_child_fmt(dn,
1225                                           "DC=@,DC=RootDNSServers,CN=MicrosoftDNS,CN=System");
1226                 if (ok == false) {
1227                         TALLOC_FREE(dn);
1228                         return WERR_NOT_ENOUGH_MEMORY;
1229                 }
1230
1231                 *_dn = dn;
1232                 return WERR_OK;
1233         }
1234
1235         /* Check non-empty names */
1236         werr = dns_name_check(mem_ctx, strlen(name), name);
1237         if (!W_ERROR_IS_OK(werr)) {
1238                 return werr;
1239         }
1240
1241         for (z = zones; z != NULL; z = z->next) {
1242                 bool match;
1243
1244                 match = dns_name_match(z->name, name, &host_part_len);
1245                 if (match) {
1246                         break;
1247                 }
1248         }
1249
1250         if (z == NULL) {
1251                 return DNS_ERR(NAME_ERROR);
1252         }
1253
1254         if (host_part_len == 0) {
1255                 dn = ldb_dn_copy(mem_ctx, z->dn);
1256                 ok = ldb_dn_add_child_fmt(dn, "DC=@");
1257                 if (! ok) {
1258                         TALLOC_FREE(dn);
1259                         return WERR_NOT_ENOUGH_MEMORY;
1260                 }
1261                 *_dn = dn;
1262                 return WERR_OK;
1263         }
1264
1265         dn = ldb_dn_copy(mem_ctx, z->dn);
1266         if (dn == NULL) {
1267                 TALLOC_FREE(dn);
1268                 return WERR_NOT_ENOUGH_MEMORY;
1269         }
1270
1271         host_part = data_blob_const(name, host_part_len);
1272
1273         ok = ldb_dn_add_child_val(dn, "DC", host_part);
1274
1275         if (ok == false) {
1276                 TALLOC_FREE(dn);
1277                 return WERR_NOT_ENOUGH_MEMORY;
1278         }
1279
1280         /*
1281          * Check the new DN here for validity, so as to catch errors
1282          * early
1283          */
1284         ok = ldb_dn_validate(dn);
1285         if (ok == false) {
1286                 TALLOC_FREE(dn);
1287                 return DNS_ERR(NAME_ERROR);
1288         }
1289
1290         /*
1291          * The value from this check is saved in the DN, and doing
1292          * this here allows an easy return here.
1293          */
1294         casefold = ldb_dn_get_casefold(dn);
1295         if (casefold == NULL) {
1296                 TALLOC_FREE(dn);
1297                 return DNS_ERR(NAME_ERROR);
1298         }
1299
1300         *_dn = dn;
1301         return WERR_OK;
1302 }
1303
1304
1305 /*
1306   see if two dns records match
1307  */
1308
1309
1310 bool dns_record_match(struct dnsp_DnssrvRpcRecord *rec1,
1311                       struct dnsp_DnssrvRpcRecord *rec2)
1312 {
1313         int i;
1314         struct in6_addr rec1_in_addr6;
1315         struct in6_addr rec2_in_addr6;
1316
1317         if (rec1->wType != rec2->wType) {
1318                 return false;
1319         }
1320
1321         /* see if the data matches */
1322         switch (rec1->wType) {
1323         case DNS_TYPE_A:
1324                 return strcmp(rec1->data.ipv4, rec2->data.ipv4) == 0;
1325         case DNS_TYPE_AAAA: {
1326                 int ret;
1327
1328                 ret = inet_pton(AF_INET6, rec1->data.ipv6, &rec1_in_addr6);
1329                 if (ret != 1) {
1330                         return false;
1331                 }
1332                 ret = inet_pton(AF_INET6, rec2->data.ipv6, &rec2_in_addr6);
1333                 if (ret != 1) {
1334                         return false;
1335                 }
1336
1337                 return memcmp(&rec1_in_addr6, &rec2_in_addr6, sizeof(rec1_in_addr6)) == 0;
1338         }
1339         case DNS_TYPE_CNAME:
1340                 return samba_dns_name_equal(rec1->data.cname,
1341                                             rec2->data.cname);
1342         case DNS_TYPE_TXT:
1343                 if (rec1->data.txt.count != rec2->data.txt.count) {
1344                         return false;
1345                 }
1346                 for (i = 0; i < rec1->data.txt.count; i++) {
1347                         if (strcmp(rec1->data.txt.str[i], rec2->data.txt.str[i]) != 0) {
1348                                 return false;
1349                         }
1350                 }
1351                 return true;
1352         case DNS_TYPE_PTR:
1353                 return samba_dns_name_equal(rec1->data.ptr, rec2->data.ptr);
1354         case DNS_TYPE_NS:
1355                 return samba_dns_name_equal(rec1->data.ns, rec2->data.ns);
1356
1357         case DNS_TYPE_SRV:
1358                 return rec1->data.srv.wPriority == rec2->data.srv.wPriority &&
1359                         rec1->data.srv.wWeight  == rec2->data.srv.wWeight &&
1360                         rec1->data.srv.wPort    == rec2->data.srv.wPort &&
1361                         samba_dns_name_equal(rec1->data.srv.nameTarget,
1362                                              rec2->data.srv.nameTarget);
1363
1364         case DNS_TYPE_MX:
1365                 return rec1->data.mx.wPriority == rec2->data.mx.wPriority &&
1366                         samba_dns_name_equal(rec1->data.mx.nameTarget,
1367                                              rec2->data.mx.nameTarget);
1368
1369         case DNS_TYPE_SOA:
1370                 return samba_dns_name_equal(rec1->data.soa.mname,
1371                                             rec2->data.soa.mname) &&
1372                         samba_dns_name_equal(rec1->data.soa.rname,
1373                                              rec2->data.soa.rname) &&
1374                         rec1->data.soa.serial == rec2->data.soa.serial &&
1375                         rec1->data.soa.refresh == rec2->data.soa.refresh &&
1376                         rec1->data.soa.retry == rec2->data.soa.retry &&
1377                         rec1->data.soa.expire == rec2->data.soa.expire &&
1378                         rec1->data.soa.minimum == rec2->data.soa.minimum;
1379         case DNS_TYPE_TOMBSTONE:
1380                 return true;
1381         default:
1382                 break;
1383         }
1384
1385         return false;
1386 }
1387
1388
1389 static int dns_common_sort_zones(struct ldb_message **m1, struct ldb_message **m2)
1390 {
1391         const char *n1, *n2;
1392         size_t l1, l2;
1393
1394         n1 = ldb_msg_find_attr_as_string(*m1, "name", NULL);
1395         n2 = ldb_msg_find_attr_as_string(*m2, "name", NULL);
1396         if (n1 == NULL || n2 == NULL) {
1397                 if (n1 != NULL) {
1398                         return -1;
1399                 } else if (n2 != NULL) {
1400                         return 1;
1401                 } else {
1402                         return 0;
1403                 }
1404         }
1405         l1 = strlen(n1);
1406         l2 = strlen(n2);
1407
1408         /* If the string lengths are not equal just sort by length */
1409         if (l1 != l2) {
1410                 /* If m1 is the larger zone name, return it first */
1411                 return NUMERIC_CMP(l2, l1);
1412         }
1413
1414         /*TODO: We need to compare DNs here, we want the DomainDNSZones first */
1415         return 0;
1416 }
1417
1418 NTSTATUS dns_common_zones(struct ldb_context *samdb,
1419                           TALLOC_CTX *mem_ctx,
1420                           struct ldb_dn *base_dn,
1421                           struct dns_server_zone **zones_ret)
1422 {
1423         const struct timeval start = timeval_current();
1424         int ret;
1425         static const char * const attrs[] = { "name", NULL};
1426         struct ldb_result *res;
1427         int i;
1428         struct dns_server_zone *new_list = NULL;
1429         TALLOC_CTX *frame = talloc_stackframe();
1430         NTSTATUS result = NT_STATUS_OK;
1431
1432         if (base_dn) {
1433                 /* This search will work against windows */
1434                 ret = dsdb_search(samdb, frame, &res,
1435                                   base_dn, LDB_SCOPE_SUBTREE,
1436                                   attrs, 0, "(objectClass=dnsZone)");
1437         } else {
1438                 /* TODO: this search does not work against windows */
1439                 ret = dsdb_search(samdb, frame, &res, NULL,
1440                                   LDB_SCOPE_SUBTREE,
1441                                   attrs,
1442                                   DSDB_SEARCH_SEARCH_ALL_PARTITIONS,
1443                                   "(objectClass=dnsZone)");
1444         }
1445         if (ret != LDB_SUCCESS) {
1446                 TALLOC_FREE(frame);
1447                 result = NT_STATUS_INTERNAL_DB_CORRUPTION;
1448                 goto exit;
1449         }
1450
1451         TYPESAFE_QSORT(res->msgs, res->count, dns_common_sort_zones);
1452
1453         for (i=0; i < res->count; i++) {
1454                 struct dns_server_zone *z;
1455
1456                 z = talloc_zero(mem_ctx, struct dns_server_zone);
1457                 if (z == NULL) {
1458                         TALLOC_FREE(frame);
1459                         result = NT_STATUS_NO_MEMORY;
1460                         goto exit;
1461                 }
1462
1463                 z->name = ldb_msg_find_attr_as_string(res->msgs[i], "name", NULL);
1464                 talloc_steal(z, z->name);
1465                 z->dn = talloc_move(z, &res->msgs[i]->dn);
1466                 /*
1467                  * Ignore the RootDNSServers zone and zones that we don't support yet
1468                  * RootDNSServers should never be returned (Windows DNS server don't)
1469                  * ..TrustAnchors should never be returned as is, (Windows returns
1470                  * TrustAnchors) and for the moment we don't support DNSSEC so we'd better
1471                  * not return this zone.
1472                  */
1473                 if ((strcmp(z->name, "RootDNSServers") == 0) ||
1474                     (strcmp(z->name, "..TrustAnchors") == 0))
1475                 {
1476                         DEBUG(10, ("Ignoring zone %s\n", z->name));
1477                         talloc_free(z);
1478                         continue;
1479                 }
1480                 DLIST_ADD_END(new_list, z);
1481         }
1482
1483         *zones_ret = new_list;
1484         TALLOC_FREE(frame);
1485         result = NT_STATUS_OK;
1486 exit:
1487         DNS_COMMON_LOG_OPERATION(
1488                 nt_errstr(result),
1489                 &start,
1490                 NULL,
1491                 base_dn == NULL ? NULL : ldb_dn_get_linearized(base_dn),
1492                 NULL);
1493         return result;
1494 }
1495
1496 /*
1497   see if two DNS names are the same
1498  */
1499 bool samba_dns_name_equal(const char *name1, const char *name2)
1500 {
1501         size_t len1 = strlen(name1);
1502         size_t len2 = strlen(name2);
1503
1504         if (len1 > 0 && name1[len1 - 1] == '.') {
1505                 len1--;
1506         }
1507         if (len2 > 0 && name2[len2 - 1] == '.') {
1508                 len2--;
1509         }
1510         if (len1 != len2) {
1511                 return false;
1512         }
1513         return strncasecmp(name1, name2, len1) == 0;
1514 }
1515
1516
1517 /*
1518  * Convert unix time to a DNS timestamp
1519  * uint32 hours in the NTTIME epoch
1520  *
1521  * This uses unix_to_nt_time() which can return special flag NTTIMEs like
1522  * UINT64_MAX (0xFFF...) or NTTIME_MAX (0x7FF...), which will convert to
1523  * distant future timestamps; or 0 as a flag value, meaning a 1601 timestamp,
1524  * which is used to indicate a record does not expire.
1525  *
1526  * As we don't generally check for these special values in NTTIME conversions,
1527  * we also don't check here, but for the benefit of people encountering these
1528  * timestamps and searching for their origin, here is a list:
1529  *
1530  **  TIME_T_MAX
1531  *
1532  * Even if time_t is 32 bit, this will become NTTIME_MAX (a.k.a INT64_MAX,
1533  * 0x7fffffffffffffff) in 100ns units. That translates to 256204778 hours
1534  * since 1601, which converts back to 9223372008000000000 or
1535  * 0x7ffffff9481f1000. It will present as 30828-09-14 02:00:00, around 48
1536  * minutes earlier than NTTIME_MAX.
1537  *
1538  **  0, the start of the unix epoch, 1970-01-01 00:00:00
1539  *
1540  * This is converted into 0 in the Windows epoch, 1601-01-01 00:00:00 which is
1541  * clearly the same whether you count in 100ns units or hours. In DNS record
1542  * timestamps this is a flag meaning the record will never expire.
1543  *
1544  **  (time_t)-1, such as what *might* mean 1969-12-31 23:59:59
1545  *
1546  * This becomes (NTTIME)-1ULL a.k.a. UINT64_MAX, 0xffffffffffffffff thence
1547  * 512409557 in hours since 1601. That in turn is 0xfffffffaf2028800 or
1548  * 18446744052000000000 in NTTIME (rounded to the hour), which might be
1549  * presented as -21709551616 or -0x50dfd7800, because NTTIME is not completely
1550  * dedicated to being unsigned. If it gets shown as a year, it will be around
1551  * 60055.
1552  *
1553  **  Other negative time_t values (e.g. 1969-05-29).
1554  *
1555  * The meaning of these is somewhat undefined, but in any case they will
1556  * translate perfectly well into the same dates in NTTIME.
1557  *
1558  **  Notes
1559  *
1560  * There are dns timestamps that exceed the range of NTTIME (up to 488356 AD),
1561  * but it is not possible for this function to produce them.
1562  *
1563  * It is plausible that it was at midnight on 1601-01-01, in London, that
1564  * Shakespeare wrote:
1565  *
1566  *  The time is out of joint. O cursed spite
1567  *  That ever I was born to set it right!
1568  *
1569  * and this is why we have this epoch and time zone.
1570  */
1571 uint32_t unix_to_dns_timestamp(time_t t)
1572 {
1573         NTTIME nt;
1574         unix_to_nt_time(&nt, t);
1575         nt /= NTTIME_TO_HOURS;
1576         return (uint32_t) nt;
1577 }
1578
1579 /*
1580  * Convert a DNS timestamp into NTTIME.
1581  *
1582  * Because DNS timestamps cover a longer time period than NTTIME, and these
1583  * would wrap to an arbitrary NTTIME, we saturate at NTTIME_MAX and return an
1584  * error in this case.
1585  */
1586 NTSTATUS dns_timestamp_to_nt_time(NTTIME *_nt, uint32_t t)
1587 {
1588         NTTIME nt = t;
1589         if (nt > NTTIME_MAX / NTTIME_TO_HOURS) {
1590                 *_nt = NTTIME_MAX;
1591                 return NT_STATUS_INTEGER_OVERFLOW;
1592         }
1593         *_nt = nt * NTTIME_TO_HOURS;
1594         return NT_STATUS_OK;
1595 }