2 Unix SMB/CIFS implementation.
6 Copyright (C) 2010 Kai Blin
7 Copyright (C) 2014 Stefan Metzmacher
8 Copyright (C) 2015 Andrew Bartlett
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.
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.
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/>.
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"
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"
39 #define DBGC_CLASS DBGC_DNS
43 uint8_t werr_to_dns_err(WERROR werr
)
45 if (W_ERROR_EQUAL(WERR_OK
, werr
)) {
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
;
72 DEBUG(5, ("No mapping exists for %s\n", win_errstr(werr
)));
73 return DNS_RCODE_SERVFAIL
;
76 WERROR
dns_common_extract(struct ldb_context
*samdb
,
77 const struct ldb_message_element
*el
,
79 struct dnsp_DnssrvRpcRecord
**records
,
80 uint16_t *num_records
)
83 struct dnsp_DnssrvRpcRecord
*recs
;
88 recs
= talloc_zero_array(mem_ctx
, struct dnsp_DnssrvRpcRecord
,
91 return WERR_NOT_ENOUGH_MEMORY
;
93 for (ri
= 0; ri
< el
->num_values
; ri
++) {
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
)) {
103 DEBUG(0, ("Failed to grab dnsp_DnssrvRpcRecord\n"));
104 return DNS_ERR(SERVER_FAILURE
);
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
111 if (recs
[ri
].wType
!= DNS_TYPE_SOA
) {
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
);
126 ret
= samdb_dns_host_name(samdb
, &dnsHostName
);
127 if (ret
!= LDB_SUCCESS
|| dnsHostName
== NULL
) {
128 DEBUG(0, ("Failed to get dnsHostName from rootDSE"));
129 return DNS_ERR(SERVER_FAILURE
);
132 recs
[ri
].data
.soa
.mname
= talloc_strdup(recs
, dnsHostName
);
136 *num_records
= el
->num_values
;
141 * Lookup a DNS record, performing an exact match.
142 * i.e. DNS wild card records are not considered.
144 WERROR
dns_common_lookup(struct ldb_context
*samdb
,
147 struct dnsp_DnssrvRpcRecord
**records
,
148 uint16_t *num_records
,
151 const struct timeval start
= timeval_current();
152 static const char * const attrs
[] = {
158 WERROR werr
= WERR_OK
;
159 struct ldb_message
*msg
= NULL
;
160 struct ldb_message_element
*el
;
165 if (tombstoned
!= NULL
) {
167 ret
= dsdb_search_one(samdb
, mem_ctx
, &msg
, dn
,
168 LDB_SCOPE_BASE
, attrs
, 0,
169 "(objectClass=dnsNode)");
171 ret
= dsdb_search_one(samdb
, mem_ctx
, &msg
, dn
,
172 LDB_SCOPE_BASE
, attrs
, 0,
173 "(&(objectClass=dnsNode)(!(dNSTombstoned=TRUE)))");
175 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
176 werr
= WERR_DNS_ERROR_NAME_DOES_NOT_EXIST
;
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
);
186 if (tombstoned
!= NULL
) {
187 *tombstoned
= ldb_msg_find_attr_as_bool(msg
,
188 "dNSTombstoned", false);
191 el
= ldb_msg_find_element(msg
, "dnsRecord");
195 * records produced by older Samba releases
196 * keep dnsNode objects without dnsRecord and
197 * without setting dNSTombstoned=TRUE.
199 * We just pretend they're tombstones.
201 if (tombstoned
!= NULL
) {
202 struct dnsp_DnssrvRpcRecord
*recs
;
203 recs
= talloc_array(mem_ctx
,
204 struct dnsp_DnssrvRpcRecord
,
207 werr
= WERR_NOT_ENOUGH_MEMORY
;
210 recs
[0] = (struct dnsp_DnssrvRpcRecord
) {
211 .wType
= DNS_TYPE_TOMBSTONE
,
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()
218 .data
.EntombedTime
= 1,
228 * Because we are not looking for a tombstone
229 * in this codepath, we just pretend it does
232 werr
= WERR_DNS_ERROR_NAME_DOES_NOT_EXIST
;
237 werr
= dns_common_extract(samdb
, el
, mem_ctx
, records
, num_records
);
239 if (!W_ERROR_IS_OK(werr
)) {
245 DNS_COMMON_LOG_OPERATION(
249 dn
== NULL
? NULL
: ldb_dn_get_linearized(dn
),
255 * Build an ldb_parse_tree node for an equality check
257 * Note: name is assumed to have been validated by dns_name_check
258 * so will be zero terminated and of a reasonable size.
260 static struct ldb_parse_tree
*build_equality_operation(
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 */
268 struct ldb_parse_tree
*el
= NULL
; /* Equality node being built */
269 struct ldb_val
*value
= NULL
; /* Value the attr will be compared
271 size_t length
= 0; /* calculated length of the value
272 including option '*' prefix and
273 '\0' string terminator */
275 el
= talloc(mem_ctx
, struct ldb_parse_tree
);
277 DBG_ERR("Unable to allocate ldb_parse_tree\n");
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");
292 value
->length
= length
;
294 value
->data
[0] = '*';
296 memcpy(&value
->data
[1], name
, size
);
298 } else if (name
!= NULL
) {
299 memcpy(value
->data
, name
, size
);
305 * Determine the number of levels in name
306 * essentially the number of '.'s in the name + 1
308 * name is assumed to have been validated by dns_name_check
310 static unsigned int number_of_labels(const struct ldb_val
*name
) {
312 unsigned int labels
= 1;
313 for (x
= 0; x
< name
->length
; x
++) {
314 if (name
->data
[x
] == '.') {
321 * Build a query that matches the target name, and any possible
322 * DNS wild card entries
324 * Builds a parse tree equivalent to the example query.
326 * x.y.z -> (|(name=x.y.z)(name=\2a.y.z)(name=\2a.z)(name=\2a))
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
332 * Returns NULL if unable to build the query.
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
338 #define BASE "(&(objectClass=dnsNode)(!(dNSTombstoned=TRUE))(|(a=b)(c=d)))"
339 static struct ldb_parse_tree
*build_wildcard_query(
343 const struct ldb_val
*name
= NULL
; /* The DNS name being
345 const char *attr
= "name"; /* The attribute name */
346 struct ldb_parse_tree
*query
= NULL
; /* The constructed query
348 struct ldb_parse_tree
*wildcard_query
= NULL
; /* The parse tree for the
351 int labels
= 0; /* The number of labels in the name */
353 name
= ldb_dn_get_rdn_val(dn
);
355 DBG_ERR("Unable to get domain name value\n");
358 labels
= number_of_labels(name
);
360 query
= ldb_parse_tree(mem_ctx
, BASE
);
362 DBG_ERR("Unable to parse query %s\n", BASE
);
367 * The 3rd element of BASE is a place holder which is replaced with
368 * the actual wild card query
370 wildcard_query
= query
->u
.list
.elements
[2];
371 TALLOC_FREE(wildcard_query
->u
.list
.elements
);
373 wildcard_query
->u
.list
.num_elements
= labels
+ 1;
374 wildcard_query
->u
.list
.elements
= talloc_array(
376 struct ldb_parse_tree
*,
379 * Build the wild card query
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
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(
397 return NULL
; /* Reason will have been logged */
399 wildcard_query
->u
.list
.elements
[l
] = el
;
401 /* skip to the start of the next label */
403 for (;x
< name
->length
&& name
->data
[x
] != '.'; x
++);
406 /* Add the base level "*" only query */
407 el
= build_equality_operation(mem_ctx
, true, NULL
, attr
, 0);
410 return NULL
; /* Reason will have been logged */
412 wildcard_query
->u
.list
.elements
[l
] = el
;
418 * Scan the list of records matching a dns wildcard query and return the
421 * The best match is either an exact name match, or the longest wild card
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
427 static struct ldb_message
*get_best_match(struct ldb_dn
*dn
,
428 struct ldb_result
*result
)
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 */
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
];
445 if (candidate
->length
> length
) {
447 length
= candidate
->length
;
450 return result
->msgs
[matched
];
454 * Look up a DNS entry, if an exact match does not exist, return the
455 * closest matching DNS wildcard entry if available
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
462 static int dns_wildcard_lookup(struct ldb_context
*samdb
,
465 struct ldb_message
**msg
)
467 static const char * const attrs
[] = {
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();
480 parent
= ldb_dn_get_parent(frame
, dn
);
481 if (parent
== NULL
) {
482 DBG_ERR("Unable to extract parent from dn\n");
484 return LDB_ERR_OPERATIONS_ERROR
;
487 query
= build_wildcard_query(frame
, dn
);
490 return LDB_ERR_OPERATIONS_ERROR
;
493 result
= talloc_zero(mem_ctx
, struct ldb_result
);
494 if (result
== NULL
) {
496 DBG_ERR("Unable to allocate ldb_result\n");
497 return LDB_ERR_OPERATIONS_ERROR
;
500 ret
= ldb_build_search_req_ex(&request
,
509 ldb_search_default_callback
,
511 if (ret
!= LDB_SUCCESS
) {
513 DBG_ERR("ldb_build_search_req_ex returned %d\n", ret
);
517 ret
= ldb_request(samdb
, request
);
518 if (ret
!= LDB_SUCCESS
) {
523 ret
= ldb_wait(request
->handle
, LDB_WAIT_ALL
);
524 if (ret
!= LDB_SUCCESS
) {
529 if (result
->count
== 0) {
531 return LDB_ERR_NO_SUCH_OBJECT
;
534 match
= get_best_match(dn
, result
);
537 return LDB_ERR_OPERATIONS_ERROR
;
540 *msg
= talloc_move(mem_ctx
, &match
);
546 * Lookup a DNS record, will match DNS wild card records if an exact match
549 WERROR
dns_common_wildcard_lookup(struct ldb_context
*samdb
,
552 struct dnsp_DnssrvRpcRecord
**records
,
553 uint16_t *num_records
)
555 const struct timeval start
= timeval_current();
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
;
565 name
= ldb_dn_get_rdn_val(dn
);
567 werr
= DNS_ERR(NAME_ERROR
);
571 /* Don't look for a wildcard for @ */
572 if (name
->length
== 1 && name
->data
[0] == '@') {
573 werr
= dns_common_lookup(samdb
,
582 werr
= dns_name_check(
584 strlen((const char*)name
->data
),
585 (const char*) name
->data
);
586 if (!W_ERROR_IS_OK(werr
)) {
591 * Do a point search first, then fall back to a wildcard
592 * lookup if it does not exist
594 werr
= dns_common_lookup(samdb
,
600 if (!W_ERROR_EQUAL(werr
, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST
)) {
604 ret
= dns_wildcard_lookup(samdb
, mem_ctx
, dn
, &msg
);
605 if (ret
== LDB_ERR_OPERATIONS_ERROR
) {
606 werr
= DNS_ERR(SERVER_FAILURE
);
609 if (ret
!= LDB_SUCCESS
) {
610 werr
= DNS_ERR(NAME_ERROR
);
614 el
= ldb_msg_find_element(msg
, "dnsRecord");
616 werr
= WERR_DNS_ERROR_NAME_DOES_NOT_EXIST
;
620 werr
= dns_common_extract(samdb
, el
, mem_ctx
, records
, num_records
);
622 if (!W_ERROR_IS_OK(werr
)) {
628 DNS_COMMON_LOG_OPERATION(
632 dn
== NULL
? NULL
: ldb_dn_get_linearized(dn
),
637 static int rec_cmp(const struct dnsp_DnssrvRpcRecord
*r1
,
638 const struct dnsp_DnssrvRpcRecord
*r2
)
640 if (r1
->wType
!= r2
->wType
) {
642 * The records are sorted with higher types first,
643 * which puts tombstones (type 0) last.
645 return r2
->wType
- r1
->wType
;
648 * Then we need to sort from the oldest to newest timestamp.
650 * Note that dwTimeStamp == 0 (never expiring) records come first,
651 * then the ones whose expiry is soonest.
653 return r1
->dwTimeStamp
- r2
->dwTimeStamp
;
657 * Check for valid DNS names. These are names which:
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
665 WERROR
dns_name_check(TALLOC_CTX
*mem_ctx
, size_t len
, const char *name
)
668 unsigned int labels
= 0;
669 unsigned int label_len
= 0;
672 return WERR_DS_INVALID_DN_SYNTAX
;
675 if (len
> 1 && name
[0] == '.') {
676 return WERR_DS_INVALID_DN_SYNTAX
;
679 if ((len
- 1) > DNS_MAX_DOMAIN_LENGTH
) {
680 return WERR_DS_INVALID_DN_SYNTAX
;
683 for (i
= 0; i
< len
- 1; i
++) {
684 if (name
[i
] == '.' && name
[i
+1] == '.') {
685 return WERR_DS_INVALID_DN_SYNTAX
;
687 if (name
[i
] == '.') {
689 if (labels
> DNS_MAX_LABELS
) {
690 return WERR_DS_INVALID_DN_SYNTAX
;
695 if (label_len
> DNS_MAX_LABEL_LENGTH
) {
696 return WERR_DS_INVALID_DN_SYNTAX
;
704 static WERROR
check_name_list(TALLOC_CTX
*mem_ctx
, uint16_t rec_count
,
705 struct dnsp_DnssrvRpcRecord
*records
)
710 struct dnsp_DnssrvRpcRecord record
;
713 for (i
= 0; i
< rec_count
; i
++) {
716 switch (record
.wType
) {
719 len
= strlen(record
.data
.ns
);
720 werr
= dns_name_check(mem_ctx
, len
, record
.data
.ns
);
723 len
= strlen(record
.data
.cname
);
724 werr
= dns_name_check(mem_ctx
, len
, record
.data
.cname
);
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
)) {
732 len
= strlen(record
.data
.soa
.rname
);
733 werr
= dns_name_check(mem_ctx
, len
, record
.data
.soa
.rname
);
736 len
= strlen(record
.data
.ptr
);
737 werr
= dns_name_check(mem_ctx
, len
, record
.data
.ptr
);
740 len
= strlen(record
.data
.mx
.nameTarget
);
741 werr
= dns_name_check(mem_ctx
, len
, record
.data
.mx
.nameTarget
);
744 len
= strlen(record
.data
.srv
.nameTarget
);
745 werr
= dns_name_check(mem_ctx
, len
,
746 record
.data
.srv
.nameTarget
);
749 * In the default case, the record doesn't have a DN, so it
756 if (!W_ERROR_IS_OK(werr
)) {
764 bool dns_name_is_static(struct dnsp_DnssrvRpcRecord
*records
,
768 for (i
= 0; i
< rec_count
; i
++) {
769 if (records
[i
].wType
== DNS_TYPE_TOMBSTONE
) {
773 if (records
[i
].wType
== DNS_TYPE_SOA
||
774 records
[i
].dwTimeStamp
== 0) {
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
785 static struct IP4_ARRAY
*copy_ip4_array(TALLOC_CTX
*ctx
,
787 struct dnsp_ip4_array array
)
790 struct IP4_ARRAY
*ip4_array
= NULL
;
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
);
799 ip4_array
->AddrCount
= array
.addrCount
;
800 if (ip4_array
->AddrCount
== 0) {
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
);
812 for (i
= 0; i
< ip4_array
->AddrCount
; i
++) {
813 ip4_array
->AddrArray
[i
] = array
.addrArray
[i
];
819 bool dns_zoneinfo_load_zone_property(struct dnsserver_zoneinfo
*zoneinfo
,
820 struct dnsp_DnsProperty
*prop
)
823 case DSPROPERTY_ZONE_TYPE
:
824 zoneinfo
->dwZoneType
= prop
->data
.zone_type
;
826 case DSPROPERTY_ZONE_ALLOW_UPDATE
:
827 zoneinfo
->fAllowUpdate
= prop
->data
.allow_update_flag
;
829 case DSPROPERTY_ZONE_NOREFRESH_INTERVAL
:
830 zoneinfo
->dwNoRefreshInterval
= prop
->data
.norefresh_hours
;
832 case DSPROPERTY_ZONE_REFRESH_INTERVAL
:
833 zoneinfo
->dwRefreshInterval
= prop
->data
.refresh_hours
;
835 case DSPROPERTY_ZONE_AGING_STATE
:
836 zoneinfo
->fAging
= prop
->data
.aging_enabled
;
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
) {
845 case DSPROPERTY_ZONE_AGING_ENABLED_TIME
:
846 zoneinfo
->dwAvailForScavengeTime
=
847 prop
->data
.next_scavenging_cycle_hours
;
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
) {
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
:
869 WERROR
dns_get_zone_properties(struct ldb_context
*samdb
,
871 struct ldb_dn
*zone_dn
,
872 struct dnsserver_zoneinfo
*zoneinfo
)
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
;
882 ret
= ldb_search(samdb
,
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
);
895 element
= ldb_msg_find_element(res
->msgs
[0], "dNSProperty");
896 if (element
== NULL
) {
897 return DNS_ERR(NOTZONE
);
900 for (i
= 0; i
< element
->num_values
; i
++) {
902 prop
= talloc_zero(mem_ctx
, struct dnsp_DnsProperty
);
904 return WERR_NOT_ENOUGH_MEMORY
;
906 err
= ndr_pull_struct_blob(
907 &(element
->values
[i
]),
910 (ndr_pull_flags_fn_t
)ndr_pull_dnsp_DnsProperty
);
911 if (!NDR_ERR_CODE_IS_SUCCESS(err
)) {
913 * If we can't pull it, then there is no valid
914 * data to load into the zone, so ignore this
915 * as Micosoft does. Windows can load an
916 * invalid property with a zero length into
917 * the dnsProperty attribute.
923 dns_zoneinfo_load_zone_property(zoneinfo
, prop
);
924 if (!valid_property
) {
925 return DNS_ERR(SERVER_FAILURE
);
932 WERROR
dns_common_replace(struct ldb_context
*samdb
,
937 struct dnsp_DnssrvRpcRecord
*records
,
940 const struct timeval start
= timeval_current();
941 struct ldb_message_element
*el
;
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
;
952 msg
= ldb_msg_new(mem_ctx
);
953 W_ERROR_HAVE_NO_MEMORY(msg
);
957 zone_dn
= ldb_dn_copy(mem_ctx
, dn
);
958 if (zone_dn
== NULL
) {
959 werr
= WERR_NOT_ENOUGH_MEMORY
;
962 if (!ldb_dn_remove_child_components(zone_dn
, 1)) {
963 werr
= DNS_ERR(SERVER_FAILURE
);
966 zoneinfo
= talloc(mem_ctx
, struct dnsserver_zoneinfo
);
967 if (zoneinfo
== NULL
) {
968 werr
= WERR_NOT_ENOUGH_MEMORY
;
971 werr
= dns_get_zone_properties(samdb
, mem_ctx
, zone_dn
, zoneinfo
);
972 if (W_ERROR_EQUAL(DNS_ERR(NOTZONE
), werr
)) {
974 * We only got zoneinfo for aging so if we didn't find any
975 * properties then just disable aging and keep going.
977 zoneinfo
->fAging
= 0;
978 } else if (!W_ERROR_IS_OK(werr
)) {
982 werr
= check_name_list(mem_ctx
, rec_count
, records
);
983 if (!W_ERROR_IS_OK(werr
)) {
987 ret
= ldb_msg_add_empty(msg
, "dnsRecord", LDB_FLAG_MOD_REPLACE
, &el
);
988 if (ret
!= LDB_SUCCESS
) {
989 werr
= DNS_ERR(SERVER_FAILURE
);
994 * we have at least one value,
995 * which might be used for the tombstone marker
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
;
1003 if (rec_count
> 1) {
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
1009 TYPESAFE_QSORT(records
, rec_count
, rec_cmp
);
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
;
1016 if (records
[i
].wType
== DNS_TYPE_TOMBSTONE
) {
1018 * There are two things that could be going on here.
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
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.
1033 * It is not possible to add an explicit tombstone
1036 if (records
[i
].data
.EntombedTime
!= 0) {
1037 was_tombstoned
= true;
1042 if (zoneinfo
->fAging
== 1 && records
[i
].dwTimeStamp
!= 0) {
1043 t
= unix_to_dns_timestamp(time(NULL
));
1044 if (t
- records
[i
].dwTimeStamp
>
1045 zoneinfo
->dwNoRefreshInterval
) {
1046 records
[i
].dwTimeStamp
= t
;
1050 records
[i
].dwSerial
= serial
;
1051 ndr_err
= ndr_push_struct_blob(v
, el
->values
, &records
[i
],
1052 (ndr_push_flags_fn_t
)ndr_push_dnsp_DnssrvRpcRecord
);
1053 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1054 DEBUG(0, ("Failed to push dnsp_DnssrvRpcRecord\n"));
1055 werr
= DNS_ERR(SERVER_FAILURE
);
1063 * This is a new dnsNode, which simplifies everything as we
1064 * know there is nothing to delete or change. We add the
1065 * records and get out.
1067 if (el
->num_values
== 0) {
1072 ret
= ldb_msg_add_string(msg
, "objectClass", "dnsNode");
1073 if (ret
!= LDB_SUCCESS
) {
1074 werr
= DNS_ERR(SERVER_FAILURE
);
1078 ret
= ldb_add(samdb
, msg
);
1079 if (ret
!= LDB_SUCCESS
) {
1080 werr
= DNS_ERR(SERVER_FAILURE
);
1088 if (el
->num_values
== 0) {
1090 * We get here if there are no records or all the records were
1093 struct dnsp_DnssrvRpcRecord tbs
;
1094 struct ldb_val
*v
= &el
->values
[el
->num_values
];
1095 enum ndr_err_code ndr_err
;
1098 if (was_tombstoned
) {
1100 * This is already a tombstoned object.
1101 * Just leave it instead of updating the time stamp.
1107 tv
= timeval_current();
1108 tbs
= (struct dnsp_DnssrvRpcRecord
) {
1109 .wType
= DNS_TYPE_TOMBSTONE
,
1111 .data
.EntombedTime
= timeval_to_nttime(&tv
),
1114 ndr_err
= ndr_push_struct_blob(v
, el
->values
, &tbs
,
1115 (ndr_push_flags_fn_t
)ndr_push_dnsp_DnssrvRpcRecord
);
1116 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1117 DEBUG(0, ("Failed to push dnsp_DnssrvRpcRecord\n"));
1118 werr
= DNS_ERR(SERVER_FAILURE
);
1123 become_tombstoned
= true;
1126 if (was_tombstoned
|| become_tombstoned
) {
1127 ret
= ldb_msg_append_fmt(msg
, LDB_FLAG_MOD_REPLACE
,
1128 "dNSTombstoned", "%s",
1129 become_tombstoned
? "TRUE" : "FALSE");
1130 if (ret
!= LDB_SUCCESS
) {
1131 werr
= DNS_ERR(SERVER_FAILURE
);
1136 ret
= ldb_modify(samdb
, msg
);
1137 if (ret
!= LDB_SUCCESS
) {
1138 NTSTATUS nt
= dsdb_ldb_err_to_ntstatus(ret
);
1139 werr
= ntstatus_to_werror(nt
);
1146 DNS_COMMON_LOG_OPERATION(
1150 dn
== NULL
? NULL
: ldb_dn_get_linearized(dn
),
1155 bool dns_name_match(const char *zone
, const char *name
, size_t *host_part_len
)
1157 size_t zl
= strlen(zone
);
1158 size_t nl
= strlen(name
);
1160 static const size_t fixup
= 'a' - 'A';
1166 for (zi
= zl
, ni
= nl
; zi
>= 0; zi
--, ni
--) {
1170 /* convert to lower case */
1171 if (zc
>= 'A' && zc
<= 'Z') {
1174 if (nc
>= 'A' && nc
<= 'Z') {
1184 if (name
[ni
] != '.') {
1191 *host_part_len
= ni
+1;
1196 WERROR
dns_common_name2dn(struct ldb_context
*samdb
,
1197 struct dns_server_zone
*zones
,
1198 TALLOC_CTX
*mem_ctx
,
1200 struct ldb_dn
**_dn
)
1202 struct ldb_dn
*base
;
1204 const struct dns_server_zone
*z
;
1205 size_t host_part_len
= 0;
1206 struct ldb_val host_part
;
1209 const char *casefold
= NULL
;
1212 return DNS_ERR(FORMAT_ERROR
);
1215 if (strcmp(name
, "") == 0) {
1216 base
= ldb_get_default_basedn(samdb
);
1217 dn
= ldb_dn_copy(mem_ctx
, base
);
1218 ok
= ldb_dn_add_child_fmt(dn
,
1219 "DC=@,DC=RootDNSServers,CN=MicrosoftDNS,CN=System");
1222 return WERR_NOT_ENOUGH_MEMORY
;
1229 /* Check non-empty names */
1230 werr
= dns_name_check(mem_ctx
, strlen(name
), name
);
1231 if (!W_ERROR_IS_OK(werr
)) {
1235 for (z
= zones
; z
!= NULL
; z
= z
->next
) {
1238 match
= dns_name_match(z
->name
, name
, &host_part_len
);
1245 return DNS_ERR(NAME_ERROR
);
1248 if (host_part_len
== 0) {
1249 dn
= ldb_dn_copy(mem_ctx
, z
->dn
);
1250 ok
= ldb_dn_add_child_fmt(dn
, "DC=@");
1253 return WERR_NOT_ENOUGH_MEMORY
;
1259 dn
= ldb_dn_copy(mem_ctx
, z
->dn
);
1262 return WERR_NOT_ENOUGH_MEMORY
;
1265 host_part
= data_blob_const(name
, host_part_len
);
1267 ok
= ldb_dn_add_child_val(dn
, "DC", host_part
);
1271 return WERR_NOT_ENOUGH_MEMORY
;
1275 * Check the new DN here for validity, so as to catch errors
1278 ok
= ldb_dn_validate(dn
);
1281 return DNS_ERR(NAME_ERROR
);
1285 * The value from this check is saved in the DN, and doing
1286 * this here allows an easy return here.
1288 casefold
= ldb_dn_get_casefold(dn
);
1289 if (casefold
== NULL
) {
1291 return DNS_ERR(NAME_ERROR
);
1300 see if two dns records match
1304 bool dns_record_match(struct dnsp_DnssrvRpcRecord
*rec1
,
1305 struct dnsp_DnssrvRpcRecord
*rec2
)
1308 struct in6_addr rec1_in_addr6
;
1309 struct in6_addr rec2_in_addr6
;
1311 if (rec1
->wType
!= rec2
->wType
) {
1315 /* see if the data matches */
1316 switch (rec1
->wType
) {
1318 return strcmp(rec1
->data
.ipv4
, rec2
->data
.ipv4
) == 0;
1319 case DNS_TYPE_AAAA
: {
1322 ret
= inet_pton(AF_INET6
, rec1
->data
.ipv6
, &rec1_in_addr6
);
1326 ret
= inet_pton(AF_INET6
, rec2
->data
.ipv6
, &rec2_in_addr6
);
1331 return memcmp(&rec1_in_addr6
, &rec2_in_addr6
, sizeof(rec1_in_addr6
)) == 0;
1333 case DNS_TYPE_CNAME
:
1334 return samba_dns_name_equal(rec1
->data
.cname
,
1337 if (rec1
->data
.txt
.count
!= rec2
->data
.txt
.count
) {
1340 for (i
= 0; i
< rec1
->data
.txt
.count
; i
++) {
1341 if (strcmp(rec1
->data
.txt
.str
[i
], rec2
->data
.txt
.str
[i
]) != 0) {
1347 return samba_dns_name_equal(rec1
->data
.ptr
, rec2
->data
.ptr
);
1349 return samba_dns_name_equal(rec1
->data
.ns
, rec2
->data
.ns
);
1352 return rec1
->data
.srv
.wPriority
== rec2
->data
.srv
.wPriority
&&
1353 rec1
->data
.srv
.wWeight
== rec2
->data
.srv
.wWeight
&&
1354 rec1
->data
.srv
.wPort
== rec2
->data
.srv
.wPort
&&
1355 samba_dns_name_equal(rec1
->data
.srv
.nameTarget
,
1356 rec2
->data
.srv
.nameTarget
);
1359 return rec1
->data
.mx
.wPriority
== rec2
->data
.mx
.wPriority
&&
1360 samba_dns_name_equal(rec1
->data
.mx
.nameTarget
,
1361 rec2
->data
.mx
.nameTarget
);
1364 return samba_dns_name_equal(rec1
->data
.soa
.mname
,
1365 rec2
->data
.soa
.mname
) &&
1366 samba_dns_name_equal(rec1
->data
.soa
.rname
,
1367 rec2
->data
.soa
.rname
) &&
1368 rec1
->data
.soa
.serial
== rec2
->data
.soa
.serial
&&
1369 rec1
->data
.soa
.refresh
== rec2
->data
.soa
.refresh
&&
1370 rec1
->data
.soa
.retry
== rec2
->data
.soa
.retry
&&
1371 rec1
->data
.soa
.expire
== rec2
->data
.soa
.expire
&&
1372 rec1
->data
.soa
.minimum
== rec2
->data
.soa
.minimum
;
1373 case DNS_TYPE_TOMBSTONE
:
1383 static int dns_common_sort_zones(struct ldb_message
**m1
, struct ldb_message
**m2
)
1385 const char *n1
, *n2
;
1388 n1
= ldb_msg_find_attr_as_string(*m1
, "name", NULL
);
1389 n2
= ldb_msg_find_attr_as_string(*m2
, "name", NULL
);
1390 if (n1
== NULL
|| n2
== NULL
) {
1393 } else if (n2
!= NULL
) {
1402 /* If the string lengths are not equal just sort by length */
1404 /* If m1 is the larger zone name, return it first */
1408 /*TODO: We need to compare DNs here, we want the DomainDNSZones first */
1412 NTSTATUS
dns_common_zones(struct ldb_context
*samdb
,
1413 TALLOC_CTX
*mem_ctx
,
1414 struct ldb_dn
*base_dn
,
1415 struct dns_server_zone
**zones_ret
)
1417 const struct timeval start
= timeval_current();
1419 static const char * const attrs
[] = { "name", NULL
};
1420 struct ldb_result
*res
;
1422 struct dns_server_zone
*new_list
= NULL
;
1423 TALLOC_CTX
*frame
= talloc_stackframe();
1424 NTSTATUS result
= NT_STATUS_OK
;
1427 /* This search will work against windows */
1428 ret
= dsdb_search(samdb
, frame
, &res
,
1429 base_dn
, LDB_SCOPE_SUBTREE
,
1430 attrs
, 0, "(objectClass=dnsZone)");
1432 /* TODO: this search does not work against windows */
1433 ret
= dsdb_search(samdb
, frame
, &res
, NULL
,
1436 DSDB_SEARCH_SEARCH_ALL_PARTITIONS
,
1437 "(objectClass=dnsZone)");
1439 if (ret
!= LDB_SUCCESS
) {
1441 result
= NT_STATUS_INTERNAL_DB_CORRUPTION
;
1445 TYPESAFE_QSORT(res
->msgs
, res
->count
, dns_common_sort_zones
);
1447 for (i
=0; i
< res
->count
; i
++) {
1448 struct dns_server_zone
*z
;
1450 z
= talloc_zero(mem_ctx
, struct dns_server_zone
);
1453 result
= NT_STATUS_NO_MEMORY
;
1457 z
->name
= ldb_msg_find_attr_as_string(res
->msgs
[i
], "name", NULL
);
1458 talloc_steal(z
, z
->name
);
1459 z
->dn
= talloc_move(z
, &res
->msgs
[i
]->dn
);
1461 * Ignore the RootDNSServers zone and zones that we don't support yet
1462 * RootDNSServers should never be returned (Windows DNS server don't)
1463 * ..TrustAnchors should never be returned as is, (Windows returns
1464 * TrustAnchors) and for the moment we don't support DNSSEC so we'd better
1465 * not return this zone.
1467 if ((strcmp(z
->name
, "RootDNSServers") == 0) ||
1468 (strcmp(z
->name
, "..TrustAnchors") == 0))
1470 DEBUG(10, ("Ignoring zone %s\n", z
->name
));
1474 DLIST_ADD_END(new_list
, z
);
1477 *zones_ret
= new_list
;
1479 result
= NT_STATUS_OK
;
1481 DNS_COMMON_LOG_OPERATION(
1485 base_dn
== NULL
? NULL
: ldb_dn_get_linearized(base_dn
),
1491 see if two DNS names are the same
1493 bool samba_dns_name_equal(const char *name1
, const char *name2
)
1495 size_t len1
= strlen(name1
);
1496 size_t len2
= strlen(name2
);
1498 if (len1
> 0 && name1
[len1
- 1] == '.') {
1501 if (len2
> 0 && name2
[len2
- 1] == '.') {
1507 return strncasecmp(name1
, name2
, len1
) == 0;
1512 * Convert unix time to a DNS timestamp
1513 * uint32 hours in the NTTIME epoch
1515 * This uses unix_to_nt_time() which can return special flag NTTIMEs like
1516 * UINT64_MAX (0xFFF...) or NTTIME_MAX (0x7FF...), which will convert to
1517 * distant future timestamps; or 0 as a flag value, meaning a 1601 timestamp,
1518 * which is used to indicate a record does not expire.
1520 * As we don't generally check for these special values in NTTIME conversions,
1521 * we also don't check here, but for the benefit of people encountering these
1522 * timestamps and searching for their origin, here is a list:
1526 * Even if time_t is 32 bit, this will become NTTIME_MAX (a.k.a INT64_MAX,
1527 * 0x7fffffffffffffff) in 100ns units. That translates to 256204778 hours
1528 * since 1601, which converts back to 9223372008000000000 or
1529 * 0x7ffffff9481f1000. It will present as 30828-09-14 02:00:00, around 48
1530 * minutes earlier than NTTIME_MAX.
1532 ** 0, the start of the unix epoch, 1970-01-01 00:00:00
1534 * This is converted into 0 in the Windows epoch, 1601-01-01 00:00:00 which is
1535 * clearly the same whether you count in 100ns units or hours. In DNS record
1536 * timestamps this is a flag meaning the record will never expire.
1538 ** (time_t)-1, such as what *might* mean 1969-12-31 23:59:59
1540 * This becomes (NTTIME)-1ULL a.k.a. UINT64_MAX, 0xffffffffffffffff thence
1541 * 512409557 in hours since 1601. That in turn is 0xfffffffaf2028800 or
1542 * 18446744052000000000 in NTTIME (rounded to the hour), which might be
1543 * presented as -21709551616 or -0x50dfd7800, because NTITME is not completely
1544 * dedicated to being unsigned. If it gets shown as a year, it will be around
1547 ** Other negative time_t values (e.g. 1969-05-29).
1549 * The meaning of these is somewhat undefined, but in any case they will
1550 * translate perfectly well into the same dates in NTTIME.
1554 * There are dns timestamps that exceed the range of NTTIME (up to 488356 AD),
1555 * but it is not possible for this function to produce them.
1557 * It is plausible that it was at midnight on 1601-01-01, in London, that
1558 * Shakespeare wrote:
1560 * The time is out of joint. O cursed spite
1561 * That ever I was born to set it right!
1563 * and this is why we have this epoch and time zone.
1565 uint32_t unix_to_dns_timestamp(time_t t
)
1568 unix_to_nt_time(&nt
, t
);
1569 nt
/= NTTIME_TO_HOURS
;
1570 return (uint32_t) nt
;
1574 * Convert a DNS timestamp into NTTIME.
1576 * Because DNS timestamps cover a longer time period than NTTIME, and these
1577 * would wrap to an arbitrary NTTIME, we saturate at NTTIME_MAX and return an
1578 * error in this case.
1580 NTSTATUS
dns_timestamp_to_nt_time(NTTIME
*_nt
, uint32_t t
)
1583 if (nt
> NTTIME_MAX
/ NTTIME_TO_HOURS
) {
1585 return NT_STATUS_INTEGER_OVERFLOW
;
1587 *_nt
= nt
* NTTIME_TO_HOURS
;
1588 return NT_STATUS_OK
;