1 /*
2 Unix SMB/CIFS implementation.
3
4 DNS Server
5
6 Copyright (C) Amitay Isaacs 2011
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "dnsserver.h"
24 #include "lib/util/dlinklist.h"
25 #include "librpc/gen_ndr/ndr_dnsp.h"
26 #include "librpc/gen_ndr/ndr_security.h"
27 #include "librpc/gen_ndr/ndr_misc.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "libcli/security/security.h"
30 #include "dsdb/common/util.h"
31
32 /* There are only 2 fixed partitions for DNS */
dnsserver_db_enumerate_partitions(TALLOC_CTX * mem_ctx,struct dnsserver_serverinfo * serverinfo,struct ldb_context * samdb)33 struct dnsserver_partition *dnsserver_db_enumerate_partitions(TALLOC_CTX *mem_ctx,
34 struct dnsserver_serverinfo *serverinfo,
35 struct ldb_context *samdb)
36 {
37 struct dnsserver_partition *partitions, *p;
38
39 partitions = NULL;
40
41 /* Domain partition */
42 p = talloc_zero(mem_ctx, struct dnsserver_partition);
43 if (p == NULL) {
44 goto failed;
45 }
46
47 p->partition_dn = ldb_dn_new(p, samdb, serverinfo->pszDomainDirectoryPartition);
48 if (p->partition_dn == NULL) {
49 goto failed;
50 }
51
52 p->pszDpFqdn = samdb_dn_to_dns_domain(p, p->partition_dn);
53 p->dwDpFlags = DNS_DP_AUTOCREATED | DNS_DP_DOMAIN_DEFAULT | DNS_DP_ENLISTED;
54 p->is_forest = false;
55
56 DLIST_ADD_END(partitions, p);
57
58 /* Forest Partition */
59 p = talloc_zero(mem_ctx, struct dnsserver_partition);
60 if (p == NULL) {
61 goto failed;
62 }
63
64 p->partition_dn = ldb_dn_new(p, samdb, serverinfo->pszForestDirectoryPartition);
65 if (p->partition_dn == NULL) {
66 goto failed;
67 }
68
69 p->pszDpFqdn = samdb_dn_to_dns_domain(p, p->partition_dn);
70 p->dwDpFlags = DNS_DP_AUTOCREATED | DNS_DP_FOREST_DEFAULT | DNS_DP_ENLISTED;
71 p->is_forest = true;
72
73 DLIST_ADD_END(partitions, p);
74
75 return partitions;
76
77 failed:
78 return NULL;
79
80 }
81
82
83 /* Search for all dnsZone records */
dnsserver_db_enumerate_zones(TALLOC_CTX * mem_ctx,struct ldb_context * samdb,struct dnsserver_partition * p)84 struct dnsserver_zone *dnsserver_db_enumerate_zones(TALLOC_CTX *mem_ctx,
85 struct ldb_context *samdb,
86 struct dnsserver_partition *p)
87 {
88 TALLOC_CTX *tmp_ctx;
89 const char * const attrs[] = {"name", "dNSProperty", NULL};
90 struct ldb_dn *dn;
91 struct ldb_result *res;
92 struct dnsserver_zone *zones, *z;
93 int i, j, ret;
94
95 tmp_ctx = talloc_new(mem_ctx);
96 if (tmp_ctx == NULL) {
97 return NULL;
98 }
99
100 dn = ldb_dn_copy(tmp_ctx, p->partition_dn);
101 if (dn == NULL) {
102 goto failed;
103 }
104 if (!ldb_dn_add_child_fmt(dn, "CN=MicrosoftDNS")) {
105 goto failed;
106 }
107
108 ret = ldb_search(samdb, tmp_ctx, &res, dn, LDB_SCOPE_SUBTREE,
109 attrs, "(objectClass=dnsZone)");
110 if (ret != LDB_SUCCESS) {
111 DEBUG(0, ("dnsserver: Failed to find DNS Zones in %s\n",
112 ldb_dn_get_linearized(dn)));
113 goto failed;
114 }
115
116 zones = NULL;
117 for(i=0; i<res->count; i++) {
118 char *name;
119 struct ldb_message_element *element = NULL;
120 struct dnsp_DnsProperty *props = NULL;
121 enum ndr_err_code err;
122 z = talloc_zero(mem_ctx, struct dnsserver_zone);
123 if (z == NULL) {
124 goto failed;
125 }
126
127 z->partition = p;
128 name = talloc_strdup(z,
129 ldb_msg_find_attr_as_string(res->msgs[i],
130 "name", NULL));
131 if (strcmp(name, "..TrustAnchors") == 0) {
132 talloc_free(z);
133 continue;
134 }
135 if (strcmp(name, "RootDNSServers") == 0) {
136 talloc_free(name);
137 z->name = talloc_strdup(z, ".");
138 } else {
139 z->name = name;
140 }
141 z->zone_dn = talloc_steal(z, res->msgs[i]->dn);
142
143 DLIST_ADD_END(zones, z);
144 DEBUG(2, ("dnsserver: Found DNS zone %s\n", z->name));
145
146 element = ldb_msg_find_element(res->msgs[i], "dNSProperty");
147 if(element != NULL){
148 props = talloc_zero_array(tmp_ctx,
149 struct dnsp_DnsProperty,
150 element->num_values);
151 for (j = 0; j < element->num_values; j++ ) {
152 err = ndr_pull_struct_blob(
153 &(element->values[j]),
154 mem_ctx,
155 &props[j],
156 (ndr_pull_flags_fn_t)
157 ndr_pull_dnsp_DnsProperty);
158 if (!NDR_ERR_CODE_IS_SUCCESS(err)){
159 /*
160 * Per Microsoft we must
161 * ignore invalid data here
162 * and continue as a Windows
163 * server can put in a
164 * structure with an invalid
165 * length.
166 *
167 * We can safely fill in an
168 * extra empty property here
169 * because
170 * dns_zoneinfo_load_zone_property()
171 * just ignores
172 * DSPROPERTY_ZONE_EMPTY
173 */
174 ZERO_STRUCT(props[j]);
175 props[j].id = DSPROPERTY_ZONE_EMPTY;
176 continue;
177 }
178 }
179 z->tmp_props = props;
180 z->num_props = element->num_values;
181 }
182 }
183 return zones;
184
185 failed:
186 talloc_free(tmp_ctx);
187 return NULL;
188 }
189
190
191 /* Find DNS partition information */
dnsserver_db_partition_info(TALLOC_CTX * mem_ctx,struct ldb_context * samdb,struct dnsserver_partition * p)192 struct dnsserver_partition_info *dnsserver_db_partition_info(TALLOC_CTX *mem_ctx,
193 struct ldb_context *samdb,
194 struct dnsserver_partition *p)
195 {
196 const char * const attrs[] = { "instanceType", "msDs-masteredBy", NULL };
197 const char * const attrs_none[] = { NULL };
198 struct ldb_result *res;
199 struct ldb_message_element *el;
200 struct ldb_dn *dn;
201 struct dnsserver_partition_info *partinfo;
202 int i, ret, instance_type;
203 TALLOC_CTX *tmp_ctx;
204
205 tmp_ctx = talloc_new(mem_ctx);
206 if (tmp_ctx == NULL) {
207 return NULL;
208 }
209
210 partinfo = talloc_zero(mem_ctx, struct dnsserver_partition_info);
211 if (partinfo == NULL) {
212 talloc_free(tmp_ctx);
213 return NULL;
214 }
215
216 /* Search for the active replica and state */
217 ret = ldb_search(samdb, tmp_ctx, &res, p->partition_dn, LDB_SCOPE_BASE,
218 attrs, NULL);
219 if (ret != LDB_SUCCESS || res->count != 1) {
220 goto failed;
221 }
222
223 /* Set the state of the partition */
224 instance_type = ldb_msg_find_attr_as_int(res->msgs[0], "instanceType", -1);
225 if (instance_type == -1) {
226 partinfo->dwState = DNS_DP_STATE_UNKNOWN;
227 } else if (instance_type & INSTANCE_TYPE_NC_COMING) {
228 partinfo->dwState = DNS_DP_STATE_REPL_INCOMING;
229 } else if (instance_type & INSTANCE_TYPE_NC_GOING) {
230 partinfo->dwState = DNS_DP_STATE_REPL_OUTGOING;
231 } else {
232 partinfo->dwState = DNS_DP_OKAY;
233 }
234
235 el = ldb_msg_find_element(res->msgs[0], "msDs-masteredBy");
236 if (el == NULL) {
237 partinfo->dwReplicaCount = 0;
238 partinfo->ReplicaArray = NULL;
239 } else {
240 partinfo->dwReplicaCount = el->num_values;
241 partinfo->ReplicaArray = talloc_zero_array(partinfo,
242 struct DNS_RPC_DP_REPLICA *,
243 el->num_values);
244 if (partinfo->ReplicaArray == NULL) {
245 goto failed;
246 }
247 for (i=0; i<el->num_values; i++) {
248 partinfo->ReplicaArray[i] = talloc_zero(partinfo,
249 struct DNS_RPC_DP_REPLICA);
250 if (partinfo->ReplicaArray[i] == NULL) {
251 goto failed;
252 }
253 partinfo->ReplicaArray[i]->pszReplicaDn = talloc_strdup(
254 partinfo,
255 (const char *)el->values[i].data);
256 if (partinfo->ReplicaArray[i]->pszReplicaDn == NULL) {
257 goto failed;
258 }
259 }
260 }
261 talloc_free(res);
262
263 /* Search for cross-reference object */
264 dn = ldb_dn_copy(tmp_ctx, ldb_get_config_basedn(samdb));
265 if (dn == NULL) {
266 goto failed;
267 }
268
269 ret = ldb_search(samdb, tmp_ctx, &res, dn, LDB_SCOPE_DEFAULT, attrs_none,
270 "(nCName=%s)", ldb_dn_get_linearized(p->partition_dn));
271 if (ret != LDB_SUCCESS || res->count != 1) {
272 goto failed;
273 }
274 partinfo->pszCrDn = talloc_strdup(partinfo, ldb_dn_get_linearized(res->msgs[0]->dn));
275 if (partinfo->pszCrDn == NULL) {
276 goto failed;
277 }
278 talloc_free(res);
279
280 talloc_free(tmp_ctx);
281 return partinfo;
282
283 failed:
284 talloc_free(tmp_ctx);
285 talloc_free(partinfo);
286 return NULL;
287 }
288
289
290 /* Increment serial number and update timestamp */
dnsserver_update_soa(TALLOC_CTX * mem_ctx,struct ldb_context * samdb,struct dnsserver_zone * z,WERROR * werr)291 static unsigned int dnsserver_update_soa(TALLOC_CTX *mem_ctx,
292 struct ldb_context *samdb,
293 struct dnsserver_zone *z,
294 WERROR *werr)
295 {
296 const char * const attrs[] = { "dnsRecord", NULL };
297 struct ldb_result *res;
298 struct dnsp_DnssrvRpcRecord rec;
299 struct ldb_message_element *el;
300 enum ndr_err_code ndr_err;
301 int ret, i, serial = -1;
302
303 *werr = WERR_INTERNAL_DB_ERROR;
304
305 ret = ldb_search(samdb, mem_ctx, &res, z->zone_dn, LDB_SCOPE_ONELEVEL, attrs,
306 "(&(objectClass=dnsNode)(name=@))");
307 if (ret != LDB_SUCCESS || res->count == 0) {
308 return -1;
309 }
310
311 el = ldb_msg_find_element(res->msgs[0], "dnsRecord");
312 if (el == NULL) {
313 return -1;
314 }
315
316 for (i=0; i<el->num_values; i++) {
317 ndr_err = ndr_pull_struct_blob(&el->values[i], mem_ctx, &rec,
318 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
319 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
320 continue;
321 }
322
323 if (rec.wType == DNS_TYPE_SOA) {
324 serial = rec.data.soa.serial + 1;
325 rec.dwSerial = serial;
326 rec.dwTimeStamp = 0;
327 rec.data.soa.serial = serial;
328
329 ndr_err = ndr_push_struct_blob(&el->values[i], mem_ctx, &rec,
330 (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord);
331 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
332 *werr = WERR_NOT_ENOUGH_MEMORY;
333 return -1;
334 }
335 break;
336 }
337 }
338
339 if (serial != -1) {
340 el->flags = LDB_FLAG_MOD_REPLACE;
341 ret = ldb_modify(samdb, res->msgs[0]);
342 if (ret != LDB_SUCCESS) {
343 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
344 *werr = WERR_ACCESS_DENIED;
345 }
346 return -1;
347 }
348 }
349
350 *werr = WERR_OK;
351
352 return serial;
353 }
354
355
356 /* Add DNS record to the database */
dnsserver_db_do_add_rec(TALLOC_CTX * mem_ctx,struct ldb_context * samdb,struct ldb_dn * dn,int num_rec,struct dnsp_DnssrvRpcRecord * rec)357 static WERROR dnsserver_db_do_add_rec(TALLOC_CTX *mem_ctx,
358 struct ldb_context *samdb,
359 struct ldb_dn *dn,
360 int num_rec,
361 struct dnsp_DnssrvRpcRecord *rec)
362 {
363 struct ldb_message *msg;
364 struct ldb_val v;
365 int ret;
366 enum ndr_err_code ndr_err;
367 int i;
368
369 msg = ldb_msg_new(mem_ctx);
370 W_ERROR_HAVE_NO_MEMORY(msg);
371
372 msg->dn = dn;
373 ret = ldb_msg_add_string(msg, "objectClass", "dnsNode");
374 if (ret != LDB_SUCCESS) {
375 return WERR_NOT_ENOUGH_MEMORY;
376 }
377
378 if (num_rec > 0 && rec) {
379 for (i=0; i<num_rec; i++) {
380 ndr_err = ndr_push_struct_blob(&v, mem_ctx, &rec[i],
381 (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord);
382 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
383 return WERR_GEN_FAILURE;
384 }
385
386 ret = ldb_msg_add_value(msg, "dnsRecord", &v, NULL);
387 if (ret != LDB_SUCCESS) {
388 return WERR_NOT_ENOUGH_MEMORY;
389 }
390 }
391 }
392
393 ret = ldb_add(samdb, msg);
394 if (ret != LDB_SUCCESS) {
395 return WERR_INTERNAL_DB_ERROR;
396 }
397
398 return WERR_OK;
399 }
400
401
402 /* Add dnsNode record to the database with DNS record */
dnsserver_db_add_empty_node(TALLOC_CTX * mem_ctx,struct ldb_context * samdb,struct dnsserver_zone * z,const char * name)403 WERROR dnsserver_db_add_empty_node(TALLOC_CTX *mem_ctx,
404 struct ldb_context *samdb,
405 struct dnsserver_zone *z,
406 const char *name)
407 {
408 const char * const attrs[] = { "name", NULL };
409 struct ldb_result *res;
410 struct ldb_dn *dn;
411 char *encoded_name = ldb_binary_encode_string(mem_ctx, name);
412 struct ldb_val name_val = data_blob_string_const(name);
413 int ret;
414
415 ret = ldb_search(samdb, mem_ctx, &res, z->zone_dn, LDB_SCOPE_BASE, attrs,
416 "(&(objectClass=dnsNode)(name=%s))",
417 encoded_name);
418 if (ret != LDB_SUCCESS) {
419 return WERR_INTERNAL_DB_ERROR;
420 }
421
422 if (res->count > 0) {
423 talloc_free(res);
424 return WERR_DNS_ERROR_RECORD_ALREADY_EXISTS;
425 }
426
427 dn = ldb_dn_copy(mem_ctx, z->zone_dn);
428 W_ERROR_HAVE_NO_MEMORY(dn);
429
430 if (!ldb_dn_add_child_val(dn, "DC", name_val)) {
431 return WERR_NOT_ENOUGH_MEMORY;
432 }
433
434 return dnsserver_db_do_add_rec(mem_ctx, samdb, dn, 0, NULL);
435 }
436
437
438 /* Add a DNS record */
dnsserver_db_add_record(TALLOC_CTX * mem_ctx,struct ldb_context * samdb,struct dnsserver_zone * z,const char * name,struct DNS_RPC_RECORD * add_record)439 WERROR dnsserver_db_add_record(TALLOC_CTX *mem_ctx,
440 struct ldb_context *samdb,
441 struct dnsserver_zone *z,
442 const char *name,
443 struct DNS_RPC_RECORD *add_record)
444 {
445 const char * const attrs[] = { "dnsRecord", "dNSTombstoned", NULL };
446 struct ldb_result *res;
447 struct dnsp_DnssrvRpcRecord *rec = NULL;
448 struct ldb_message_element *el;
449 struct ldb_dn *dn;
450 enum ndr_err_code ndr_err;
451 int ret, i;
452 int serial;
453 WERROR werr;
454 bool was_tombstoned = false;
455 char *encoded_name = ldb_binary_encode_string(mem_ctx, name);
456
457 werr = dns_to_dnsp_convert(mem_ctx, add_record, &rec, true);
458 if (!W_ERROR_IS_OK(werr)) {
459 return werr;
460 }
461
462 /* Set the correct rank for the record. */
463 if (z->zoneinfo->dwZoneType == DNS_ZONE_TYPE_PRIMARY) {
464 if (strcmp(name, "@") != 0 && rec->wType == DNS_TYPE_NS) {
465 rec->rank = DNS_RANK_NS_GLUE;
466 } else {
467 rec->rank |= DNS_RANK_ZONE;
468 }
469 } else if (strcmp(z->name, ".") == 0) {
470 rec->rank |= DNS_RANK_ROOT_HINT;
471 }
472
473 serial = dnsserver_update_soa(mem_ctx, samdb, z, &werr);
474 if (serial < 0) {
475 return werr;
476 }
477
478 rec->dwSerial = serial;
479 rec->dwTimeStamp = 0;
480
481 ret = ldb_search(samdb, mem_ctx, &res, z->zone_dn, LDB_SCOPE_ONELEVEL, attrs,
482 "(&(objectClass=dnsNode)(name=%s))",
483 encoded_name);
484 if (ret != LDB_SUCCESS) {
485 return WERR_INTERNAL_DB_ERROR;
486 }
487
488 if (res->count == 0) {
489 dn = dnsserver_name_to_dn(mem_ctx, z, name);
490 W_ERROR_HAVE_NO_MEMORY(dn);
491
492 return dnsserver_db_do_add_rec(mem_ctx, samdb, dn, 1, rec);
493 }
494
495 el = ldb_msg_find_element(res->msgs[0], "dnsRecord");
496 if (el == NULL) {
497 ret = ldb_msg_add_empty(res->msgs[0], "dnsRecord", 0, &el);
498 if (ret != LDB_SUCCESS) {
499 return WERR_NOT_ENOUGH_MEMORY;
500 }
501 }
502
503 was_tombstoned = ldb_msg_find_attr_as_bool(res->msgs[0],
504 "dNSTombstoned", false);
505 if (was_tombstoned) {
506 el->num_values = 0;
507 }
508
509 for (i=0; i<el->num_values; i++) {
510 struct dnsp_DnssrvRpcRecord rec2;
511
512 ndr_err = ndr_pull_struct_blob(&el->values[i], mem_ctx, &rec2,
513 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
514 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
515 return WERR_GEN_FAILURE;
516 }
517
518 if (dns_record_match(rec, &rec2)) {
519 break;
520 }
521 }
522 if (i < el->num_values) {
523 return WERR_DNS_ERROR_RECORD_ALREADY_EXISTS;
524 }
525 if (i == el->num_values) {
526 /* adding a new value */
527 el->values = talloc_realloc(el, el->values, struct ldb_val, el->num_values+1);
528 W_ERROR_HAVE_NO_MEMORY(el->values);
529 el->num_values++;
530 }
531
532 ndr_err = ndr_push_struct_blob(&el->values[i], mem_ctx, rec,
533 (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord);
534 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
535 return WERR_GEN_FAILURE;
536 }
537
538 el->flags = LDB_FLAG_MOD_REPLACE;
539
540 el = ldb_msg_find_element(res->msgs[0], "dNSTombstoned");
541 if (el != NULL) {
542 el->flags = LDB_FLAG_MOD_DELETE;
543 }
544
545 ret = ldb_modify(samdb, res->msgs[0]);
546 if (ret != LDB_SUCCESS) {
547 return WERR_INTERNAL_DB_ERROR;
548 }
549
550 return WERR_OK;
551 }
552
553
554 /* Update a DNS record */
dnsserver_db_update_record(TALLOC_CTX * mem_ctx,struct ldb_context * samdb,struct dnsserver_zone * z,const char * name,struct DNS_RPC_RECORD * add_record,struct DNS_RPC_RECORD * del_record)555 WERROR dnsserver_db_update_record(TALLOC_CTX *mem_ctx,
556 struct ldb_context *samdb,
557 struct dnsserver_zone *z,
558 const char *name,
559 struct DNS_RPC_RECORD *add_record,
560 struct DNS_RPC_RECORD *del_record)
561 {
562 const char * const attrs[] = { "dnsRecord", NULL };
563 struct ldb_result *res;
564 struct dnsp_DnssrvRpcRecord *arec = NULL, *drec = NULL;
565 struct ldb_message_element *el;
566 enum ndr_err_code ndr_err;
567 int ret, i;
568 int serial;
569 WERROR werr;
570 char *encoded_name = ldb_binary_encode_string(mem_ctx, name);
571
572 werr = dns_to_dnsp_convert(mem_ctx, add_record, &arec, true);
573 if (!W_ERROR_IS_OK(werr)) {
574 return werr;
575 }
576
577 werr = dns_to_dnsp_convert(mem_ctx, del_record, &drec, true);
578 if (!W_ERROR_IS_OK(werr)) {
579 return werr;
580 }
581
582 arec->dwTimeStamp = 0;
583
584 ret = ldb_search(samdb, mem_ctx, &res, z->zone_dn, LDB_SCOPE_ONELEVEL, attrs,
585 "(&(objectClass=dnsNode)(name=%s)(!(dNSTombstoned=TRUE)))",
586 encoded_name);
587 if (ret != LDB_SUCCESS) {
588 return WERR_INTERNAL_DB_ERROR;
589 }
590
591 if (res->count == 0) {
592 return WERR_DNS_ERROR_RECORD_DOES_NOT_EXIST;
593 }
594
595 el = ldb_msg_find_element(res->msgs[0], "dnsRecord");
596 if (el == NULL || el->num_values == 0) {
597 return WERR_DNS_ERROR_RECORD_DOES_NOT_EXIST;
598 }
599
600 for (i=0; i<el->num_values; i++) {
601 struct dnsp_DnssrvRpcRecord rec2;
602
603 ndr_err = ndr_pull_struct_blob(&el->values[i], mem_ctx, &rec2,
604 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
605 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
606 return WERR_GEN_FAILURE;
607 }
608
609 if (dns_record_match(arec, &rec2)) {
610 break;
611 }
612 }
613 if (i < el->num_values) {
614 return WERR_DNS_ERROR_RECORD_ALREADY_EXISTS;
615 }
616
617
618 for (i=0; i<el->num_values; i++) {
619 struct dnsp_DnssrvRpcRecord rec2;
620
621 ndr_err = ndr_pull_struct_blob(&el->values[i], mem_ctx, &rec2,
622 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
623 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
624 return WERR_GEN_FAILURE;
625 }
626
627 if (dns_record_match(drec, &rec2)) {
628 break;
629 }
630 }
631 if (i == el->num_values) {
632 return WERR_DNS_ERROR_RECORD_DOES_NOT_EXIST;
633 }
634
635 /* If updating SOA record, use specified serial, otherwise increment */
636 if (arec->wType != DNS_TYPE_SOA) {
637 serial = dnsserver_update_soa(mem_ctx, samdb, z, &werr);
638 if (serial < 0) {
639 return werr;
640 }
641 arec->dwSerial = serial;
642 }
643
644 ndr_err = ndr_push_struct_blob(&el->values[i], mem_ctx, arec,
645 (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord);
646 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
647 return WERR_GEN_FAILURE;
648 }
649
650 el->flags = LDB_FLAG_MOD_REPLACE;
651 ret = ldb_modify(samdb, res->msgs[0]);
652 if (ret != LDB_SUCCESS) {
653 return WERR_INTERNAL_DB_ERROR;
654 }
655
656 return WERR_OK;
657 }
658
659
660 /* Delete a DNS record */
dnsserver_db_delete_record(TALLOC_CTX * mem_ctx,struct ldb_context * samdb,struct dnsserver_zone * z,const char * name,struct DNS_RPC_RECORD * del_record)661 WERROR dnsserver_db_delete_record(TALLOC_CTX *mem_ctx,
662 struct ldb_context *samdb,
663 struct dnsserver_zone *z,
664 const char *name,
665 struct DNS_RPC_RECORD *del_record)
666 {
667 const char * const attrs[] = { "dnsRecord", NULL };
668 struct ldb_result *res;
669 struct dnsp_DnssrvRpcRecord *rec = NULL;
670 struct ldb_message_element *el;
671 enum ndr_err_code ndr_err;
672 int ret, i;
673 int serial;
674 WERROR werr;
675
676 serial = dnsserver_update_soa(mem_ctx, samdb, z, &werr);
677 if (serial < 0) {
678 return werr;
679 }
680
681 werr = dns_to_dnsp_convert(mem_ctx, del_record, &rec, false);
682 if (!W_ERROR_IS_OK(werr)) {
683 return werr;
684 }
685
686 ret = ldb_search(samdb, mem_ctx, &res, z->zone_dn, LDB_SCOPE_ONELEVEL, attrs,
687 "(&(objectClass=dnsNode)(name=%s))",
688 ldb_binary_encode_string(mem_ctx, name));
689 if (ret != LDB_SUCCESS) {
690 return WERR_INTERNAL_DB_ERROR;
691 }
692
693 if (res->count == 0) {
694 return WERR_DNS_ERROR_RECORD_DOES_NOT_EXIST;
695 }
696 if (res->count > 1) {
697 return WERR_DNS_ERROR_RCODE_SERVER_FAILURE;
698 }
699
700 el = ldb_msg_find_element(res->msgs[0], "dnsRecord");
701 if (el == NULL || el->num_values == 0) {
702 return WERR_DNS_ERROR_RECORD_DOES_NOT_EXIST;
703 }
704
705 for (i=0; i<el->num_values; i++) {
706 struct dnsp_DnssrvRpcRecord rec2;
707
708 ndr_err = ndr_pull_struct_blob(&el->values[i], mem_ctx, &rec2,
709 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
710 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
711 return WERR_GEN_FAILURE;
712 }
713
714 if (dns_record_match(rec, &rec2)) {
715 break;
716 }
717 }
718 if (i == el->num_values) {
719 return WERR_DNS_ERROR_RECORD_DOES_NOT_EXIST;
720 }
721 if (i < el->num_values-1) {
722 memmove(&el->values[i], &el->values[i+1], sizeof(el->values[0])*((el->num_values-1)-i));
723 }
724 el->num_values--;
725
726 if (el->num_values == 0) {
727 ret = ldb_delete(samdb, res->msgs[0]->dn);
728 } else {
729 el->flags = LDB_FLAG_MOD_REPLACE;
730 ret = ldb_modify(samdb, res->msgs[0]);
731 }
732 if (ret != LDB_SUCCESS) {
733 return WERR_INTERNAL_DB_ERROR;
734 }
735
736 return WERR_OK;
737 }
738
739
dnsserver_db_msg_add_dnsproperty(TALLOC_CTX * mem_ctx,struct ldb_message * msg,struct dnsp_DnsProperty * prop)740 static bool dnsserver_db_msg_add_dnsproperty(TALLOC_CTX *mem_ctx,
741 struct ldb_message *msg,
742 struct dnsp_DnsProperty *prop)
743 {
744 DATA_BLOB *prop_blob;
745 enum ndr_err_code ndr_err;
746 int ret;
747
748 prop_blob = talloc_zero(mem_ctx, DATA_BLOB);
749 if (prop_blob == NULL) return false;
750
751 ndr_err = ndr_push_struct_blob(prop_blob, mem_ctx, prop,
752 (ndr_push_flags_fn_t)ndr_push_dnsp_DnsProperty);
753 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
754 return false;
755 }
756 ret = ldb_msg_add_steal_value(msg, "dNSProperty", prop_blob);
757 if (ret != LDB_SUCCESS) {
758 return false;
759 }
760 return true;
761 }
762
dnsserver_db_do_reset_dword(struct ldb_context * samdb,struct dnsserver_zone * z,struct DNS_RPC_NAME_AND_PARAM * n_p)763 WERROR dnsserver_db_do_reset_dword(struct ldb_context *samdb,
764 struct dnsserver_zone *z,
765 struct DNS_RPC_NAME_AND_PARAM *n_p)
766 {
767 struct ldb_message_element *element = NULL;
768 struct dnsp_DnsProperty *prop = NULL;
769 enum ndr_err_code err;
770 TALLOC_CTX *tmp_ctx = NULL;
771 const char * const attrs[] = {"dNSProperty", NULL};
772 struct ldb_result *res = NULL;
773 int i, ret, prop_id;
774
775 if (strcasecmp(n_p->pszNodeName, "Aging") == 0) {
776 z->zoneinfo->fAging = n_p->dwParam;
777 prop_id = DSPROPERTY_ZONE_AGING_STATE;
778 } else if (strcasecmp(n_p->pszNodeName, "RefreshInterval") == 0) {
779 z->zoneinfo->dwRefreshInterval = n_p->dwParam;
780 prop_id = DSPROPERTY_ZONE_REFRESH_INTERVAL;
781 } else if (strcasecmp(n_p->pszNodeName, "NoRefreshInterval") == 0) {
782 z->zoneinfo->dwNoRefreshInterval = n_p->dwParam;
783 prop_id = DSPROPERTY_ZONE_NOREFRESH_INTERVAL;
784 } else if (strcasecmp(n_p->pszNodeName, "AllowUpdate") == 0) {
785 z->zoneinfo->fAllowUpdate = n_p->dwParam;
786 prop_id = DSPROPERTY_ZONE_ALLOW_UPDATE;
787 } else {
788 return WERR_UNKNOWN_PROPERTY;
789 }
790
791 tmp_ctx = talloc_new(NULL);
792 if (tmp_ctx == NULL) {
793 return WERR_NOT_ENOUGH_MEMORY;
794 }
795
796 ret = ldb_search(samdb, tmp_ctx, &res, z->zone_dn, LDB_SCOPE_BASE,
797 attrs, "(objectClass=dnsZone)");
798 if (ret != LDB_SUCCESS) {
799 DBG_ERR("dnsserver: no zone: %s\n",
800 ldb_dn_get_linearized(z->zone_dn));
801 TALLOC_FREE(tmp_ctx);
802 return WERR_INTERNAL_DB_ERROR;
803 }
804
805 if (res->count != 1) {
806 DBG_ERR("dnsserver: duplicate zone: %s\n",
807 ldb_dn_get_linearized(z->zone_dn));
808 TALLOC_FREE(tmp_ctx);
809 return WERR_GEN_FAILURE;
810 }
811
812 element = ldb_msg_find_element(res->msgs[0], "dNSProperty");
813 if (element == NULL) {
814 DBG_ERR("dnsserver: zone %s has no properties.\n",
815 ldb_dn_get_linearized(z->zone_dn));
816 TALLOC_FREE(tmp_ctx);
817 return WERR_INTERNAL_DB_ERROR;
818 }
819
820 for (i = 0; i < element->num_values; i++) {
821 prop = talloc_zero(element, struct dnsp_DnsProperty);
822 if (prop == NULL) {
823 TALLOC_FREE(tmp_ctx);
824 return WERR_NOT_ENOUGH_MEMORY;
825 }
826 err = ndr_pull_struct_blob(
827 &(element->values[i]),
828 tmp_ctx,
829 prop,
830 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty);
831 if (!NDR_ERR_CODE_IS_SUCCESS(err)){
832 /*
833 * If we can't pull it then try again parsing
834 * it again. A Windows server in the domain
835 * will permit the addition of an invalidly
836 * formed property with a 0 length and cause a
837 * failure here
838 */
839 struct dnsp_DnsProperty_short
840 *short_property
841 = talloc_zero(element,
842 struct dnsp_DnsProperty_short);
843 if (short_property == NULL) {
844 TALLOC_FREE(tmp_ctx);
845 return WERR_NOT_ENOUGH_MEMORY;
846 }
847 err = ndr_pull_struct_blob_all(
848 &(element->values[i]),
849 tmp_ctx,
850 short_property,
851 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty_short);
852 if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
853 /*
854 * Unknown invalid data should be
855 * ignored and logged to match Windows
856 * behaviour
857 */
858 DBG_NOTICE("dnsserver: couldn't PULL "
859 "dnsProperty value#%d in "
860 "zone %s while trying to "
861 "reset id %d\n",
862 i,
863 ldb_dn_get_linearized(z->zone_dn),
864 prop_id);
865 continue;
866 }
867
868 /*
869 * Initialise the parts of the property not
870 * overwritten by value() in the IDL for
871 * re-push
872 */
873 *prop = (struct dnsp_DnsProperty){
874 .namelength = short_property->namelength,
875 .id = short_property->id,
876 .name = short_property->name
877 /* .data will be filled in below */
878 };
879 }
880
881 if (prop->id == prop_id) {
882 switch (prop_id) {
883 case DSPROPERTY_ZONE_AGING_STATE:
884 prop->data.aging_enabled = n_p->dwParam;
885 break;
886 case DSPROPERTY_ZONE_NOREFRESH_INTERVAL:
887 prop->data.norefresh_hours = n_p->dwParam;
888 break;
889 case DSPROPERTY_ZONE_REFRESH_INTERVAL:
890 prop->data.refresh_hours = n_p->dwParam;
891 break;
892 case DSPROPERTY_ZONE_ALLOW_UPDATE:
893 prop->data.allow_update_flag = n_p->dwParam;
894 break;
895 }
896
897 err = ndr_push_struct_blob(
898 &(element->values[i]),
899 tmp_ctx,
900 prop,
901 (ndr_push_flags_fn_t)ndr_push_dnsp_DnsProperty);
902 if (!NDR_ERR_CODE_IS_SUCCESS(err)){
903 DBG_ERR("dnsserver: couldn't PUSH dns prop id "
904 "%d in zone %s\n",
905 prop->id,
906 ldb_dn_get_linearized(z->zone_dn));
907 TALLOC_FREE(tmp_ctx);
908 return WERR_INTERNAL_DB_ERROR;
909 }
910 }
911 }
912
913 element->flags = LDB_FLAG_MOD_REPLACE;
914 ret = ldb_modify(samdb, res->msgs[0]);
915 if (ret != LDB_SUCCESS) {
916 TALLOC_FREE(tmp_ctx);
917 DBG_ERR("dnsserver: Failed to modify zone %s prop %s: %s\n",
918 z->name,
919 n_p->pszNodeName,
920 ldb_errstring(samdb));
921 return WERR_INTERNAL_DB_ERROR;
922 }
923 TALLOC_FREE(tmp_ctx);
924
925 return WERR_OK;
926 }
927
928 /* Create dnsZone record to database and set security descriptor */
dnsserver_db_do_create_zone(TALLOC_CTX * tmp_ctx,struct ldb_context * samdb,struct ldb_dn * zone_dn,struct dnsserver_zone * z)929 static WERROR dnsserver_db_do_create_zone(TALLOC_CTX *tmp_ctx,
930 struct ldb_context *samdb,
931 struct ldb_dn *zone_dn,
932 struct dnsserver_zone *z)
933 {
934 const char * const attrs[] = { "objectSID", NULL };
935 struct ldb_message *msg;
936 struct ldb_result *res;
937 struct ldb_message_element *el;
938 const char sddl_template[] = "D:AI(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;CC;;;AU)(A;;RPLCLORC;;;WD)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;CI;RPWPCRCCDCLCRCWOWDSDDTSW;;;ED)(A;CIID;RPWPCRCCDCLCRCWOWDSDDTSW;;;%s)(A;CIID;RPWPCRCCDCLCRCWOWDSDDTSW;;;ED)(OA;CIID;RPWPCR;91e647de-d96f-4b70-9557-d63ff4f3ccd8;;PS)(A;CIID;RPWPCRCCDCLCLORCWOWDSDDTSW;;;EA)(A;CIID;LC;;;RU)(A;CIID;RPWPCRCCLCLORCWOWDSDSW;;;BA)S:AI";
939 char *sddl;
940 struct dom_sid dnsadmins_sid;
941 const struct dom_sid *domain_sid;
942 struct security_descriptor *secdesc;
943 struct dnsp_DnsProperty *prop;
944 DATA_BLOB *sd_encoded;
945 enum ndr_err_code ndr_err;
946 int ret;
947
948 /* Get DnsAdmins SID */
949 ret = ldb_search(samdb, tmp_ctx, &res, ldb_get_default_basedn(samdb),
950 LDB_SCOPE_DEFAULT, attrs, "(sAMAccountName=DnsAdmins)");
951 if (ret != LDB_SUCCESS || res->count != 1) {
952 return WERR_INTERNAL_DB_ERROR;
953 }
954
955 el = ldb_msg_find_element(res->msgs[0], "objectSID");
956 if (el == NULL || el->num_values != 1) {
957 return WERR_INTERNAL_DB_ERROR;
958 }
959
960 ndr_err = ndr_pull_struct_blob(&el->values[0], tmp_ctx, &dnsadmins_sid,
961 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
962 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
963 return WERR_INTERNAL_DB_ERROR;
964 }
965
966 /* create security descriptor with DnsAdmins GUID in sddl template */
967 sddl = talloc_asprintf(tmp_ctx, sddl_template,
968 dom_sid_string(tmp_ctx, &dnsadmins_sid));
969 if (sddl == NULL) {
970 return WERR_NOT_ENOUGH_MEMORY;
971 }
972 talloc_free(res);
973
974 domain_sid = samdb_domain_sid(samdb);
975 if (domain_sid == NULL) {
976 return WERR_INTERNAL_DB_ERROR;
977 }
978
979 secdesc = sddl_decode(tmp_ctx, sddl, domain_sid);
980 if (secdesc == NULL) {
981 return WERR_GEN_FAILURE;
982 }
983
984 msg = ldb_msg_new(tmp_ctx);
985 W_ERROR_HAVE_NO_MEMORY(msg);
986
987 msg->dn = zone_dn;
988 ret = ldb_msg_add_string(msg, "objectClass", "dnsZone");
989 if (ret != LDB_SUCCESS) {
990 return WERR_NOT_ENOUGH_MEMORY;
991 }
992
993 sd_encoded = talloc_zero(tmp_ctx, DATA_BLOB);
994 W_ERROR_HAVE_NO_MEMORY(sd_encoded);
995
996 ndr_err = ndr_push_struct_blob(sd_encoded, tmp_ctx, secdesc,
997 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
998 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
999 return WERR_GEN_FAILURE;
1000 }
1001
1002 ret = ldb_msg_add_steal_value(msg, "nTSecurityDescriptor", sd_encoded);
1003 if (ret != LDB_SUCCESS) {
1004 return WERR_NOT_ENOUGH_MEMORY;
1005 }
1006
1007 /* dns zone Properties */
1008 prop = talloc_zero(tmp_ctx, struct dnsp_DnsProperty);
1009 W_ERROR_HAVE_NO_MEMORY(prop);
1010
1011 prop->version = 1;
1012
1013 /* zone type */
1014 prop->id = DSPROPERTY_ZONE_TYPE;
1015 prop->data.zone_type = z->zoneinfo->dwZoneType;
1016 if (!dnsserver_db_msg_add_dnsproperty(tmp_ctx, msg, prop)) {
1017 return WERR_NOT_ENOUGH_MEMORY;
1018 }
1019
1020 /* allow update */
1021 prop->id = DSPROPERTY_ZONE_ALLOW_UPDATE;
1022 prop->data.allow_update_flag = z->zoneinfo->fAllowUpdate;
1023 if (!dnsserver_db_msg_add_dnsproperty(tmp_ctx, msg, prop)) {
1024 return WERR_NOT_ENOUGH_MEMORY;
1025 }
1026
1027 /* secure time */
1028 prop->id = DSPROPERTY_ZONE_SECURE_TIME;
1029 prop->data.zone_secure_time = 0;
1030 if (!dnsserver_db_msg_add_dnsproperty(tmp_ctx, msg, prop)) {
1031 return WERR_NOT_ENOUGH_MEMORY;
1032 }
1033
1034 /* norefresh interval */
1035 prop->id = DSPROPERTY_ZONE_NOREFRESH_INTERVAL;
1036 prop->data.norefresh_hours = 168;
1037 if (!dnsserver_db_msg_add_dnsproperty(tmp_ctx, msg, prop)) {
1038 return WERR_NOT_ENOUGH_MEMORY;
1039 }
1040
1041 /* refresh interval */
1042 prop->id = DSPROPERTY_ZONE_REFRESH_INTERVAL;
1043 prop->data.refresh_hours = 168;
1044 if (!dnsserver_db_msg_add_dnsproperty(tmp_ctx, msg, prop)) {
1045 return WERR_NOT_ENOUGH_MEMORY;
1046 }
1047
1048 /* aging state */
1049 prop->id = DSPROPERTY_ZONE_AGING_STATE;
1050 prop->data.aging_enabled = z->zoneinfo->fAging;
1051 if (!dnsserver_db_msg_add_dnsproperty(tmp_ctx, msg, prop)) {
1052 return WERR_NOT_ENOUGH_MEMORY;
1053 }
1054
1055 /* aging enabled time */
1056 prop->id = DSPROPERTY_ZONE_AGING_ENABLED_TIME;
1057 prop->data.next_scavenging_cycle_hours = 0;
1058 if (!dnsserver_db_msg_add_dnsproperty(tmp_ctx, msg, prop)) {
1059 return WERR_NOT_ENOUGH_MEMORY;
1060 }
1061
1062 talloc_free(prop);
1063
1064 ret = ldb_add(samdb, msg);
1065 if (ret != LDB_SUCCESS) {
1066 DEBUG(0, ("dnsserver: Failed to create zone (%s): %s\n",
1067 z->name, ldb_errstring(samdb)));
1068
1069 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
1070 return WERR_ACCESS_DENIED;
1071 }
1072
1073 return WERR_INTERNAL_DB_ERROR;
1074 }
1075
1076 return WERR_OK;
1077 }
1078
1079
1080 /* Create new dnsZone record and @ record (SOA + NS) */
dnsserver_db_create_zone(struct ldb_context * samdb,struct dnsserver_partition * partitions,struct dnsserver_zone * zone,struct loadparm_context * lp_ctx)1081 WERROR dnsserver_db_create_zone(struct ldb_context *samdb,
1082 struct dnsserver_partition *partitions,
1083 struct dnsserver_zone *zone,
1084 struct loadparm_context *lp_ctx)
1085 {
1086 struct dnsserver_partition *p;
1087 bool in_forest = false;
1088 WERROR status;
1089 struct ldb_dn *dn;
1090 TALLOC_CTX *tmp_ctx;
1091 struct dnsp_DnssrvRpcRecord *dns_rec;
1092 struct dnsp_soa soa;
1093 char *tmpstr, *server_fqdn, *soa_email;
1094 struct ldb_val name_val = data_blob_string_const(zone->name);
1095
1096 /* We only support primary zones for now */
1097 if (zone->zoneinfo->dwZoneType != DNS_ZONE_TYPE_PRIMARY) {
1098 return WERR_CALL_NOT_IMPLEMENTED;
1099 }
1100
1101 /* Get the correct partition */
1102 if (zone->partition->dwDpFlags & DNS_DP_FOREST_DEFAULT) {
1103 in_forest = true;
1104 }
1105 for (p = partitions; p; p = p->next) {
1106 if (in_forest == p->is_forest) {
1107 break;
1108 }
1109 }
1110 if (p == NULL) {
1111 return WERR_DNS_ERROR_DP_DOES_NOT_EXIST;
1112 }
1113
1114 tmp_ctx = talloc_new(NULL);
1115 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1116
1117 dn = ldb_dn_copy(tmp_ctx, p->partition_dn);
1118 W_ERROR_HAVE_NO_MEMORY_AND_FREE(dn, tmp_ctx);
1119
1120 if (!ldb_dn_add_child_fmt(dn, "CN=MicrosoftDNS")) {
1121 talloc_free(tmp_ctx);
1122 return WERR_NOT_ENOUGH_MEMORY;
1123 }
1124
1125 if (!ldb_dn_add_child_val(dn, "DC", name_val)) {
1126 talloc_free(tmp_ctx);
1127 return WERR_NOT_ENOUGH_MEMORY;
1128 }
1129
1130 /* Add dnsZone record */
1131 status = dnsserver_db_do_create_zone(tmp_ctx, samdb, dn, zone);
1132 if (!W_ERROR_IS_OK(status)) {
1133 talloc_free(tmp_ctx);
1134 return status;
1135 }
1136
1137 if (!ldb_dn_add_child_fmt(dn, "DC=@")) {
1138 talloc_free(tmp_ctx);
1139 return WERR_NOT_ENOUGH_MEMORY;
1140 }
1141
1142 dns_rec = talloc_zero_array(tmp_ctx, struct dnsp_DnssrvRpcRecord, 2);
1143 W_ERROR_HAVE_NO_MEMORY_AND_FREE(dns_rec, tmp_ctx);
1144
1145 tmpstr = talloc_asprintf(tmp_ctx, "%s.%s",
1146 lpcfg_netbios_name(lp_ctx),
1147 lpcfg_realm(lp_ctx));
1148 W_ERROR_HAVE_NO_MEMORY_AND_FREE(tmpstr, tmp_ctx);
1149 server_fqdn = strlower_talloc(tmp_ctx, tmpstr);
1150 W_ERROR_HAVE_NO_MEMORY_AND_FREE(server_fqdn, tmp_ctx);
1151 talloc_free(tmpstr);
1152
1153 tmpstr = talloc_asprintf(tmp_ctx, "hostmaster.%s",
1154 lpcfg_realm(lp_ctx));
1155 W_ERROR_HAVE_NO_MEMORY_AND_FREE(tmpstr, tmp_ctx);
1156 soa_email = strlower_talloc(tmp_ctx, tmpstr);
1157 W_ERROR_HAVE_NO_MEMORY_AND_FREE(soa_email, tmp_ctx);
1158 talloc_free(tmpstr);
1159
1160 /* SOA Record - values same as defined in provision/sambadns.py */
1161 soa.serial = 1;
1162 soa.refresh = 900;
1163 soa.retry = 600;
1164 soa.expire = 86400;
1165 soa.minimum = 3600;
1166 soa.mname = server_fqdn;
1167 soa.rname = soa_email;
1168
1169 dns_rec[0].wType = DNS_TYPE_SOA;
1170 dns_rec[0].rank = DNS_RANK_ZONE;
1171 dns_rec[0].dwSerial = soa.serial;
1172 dns_rec[0].dwTtlSeconds = 3600;
1173 dns_rec[0].dwTimeStamp = 0;
1174 dns_rec[0].data.soa = soa;
1175
1176 /* NS Record */
1177 dns_rec[1].wType = DNS_TYPE_NS;
1178 dns_rec[1].rank = DNS_RANK_ZONE;
1179 dns_rec[1].dwSerial = soa.serial;
1180 dns_rec[1].dwTtlSeconds = 3600;
1181 dns_rec[1].dwTimeStamp = 0;
1182 dns_rec[1].data.ns = server_fqdn;
1183
1184 /* Add @ Record */
1185 status = dnsserver_db_do_add_rec(tmp_ctx, samdb, dn, 2, dns_rec);
1186
1187 talloc_free(tmp_ctx);
1188 return status;
1189 }
1190
1191
1192 /* Delete dnsZone record and all DNS records in the zone */
dnsserver_db_delete_zone(struct ldb_context * samdb,struct dnsserver_zone * zone)1193 WERROR dnsserver_db_delete_zone(struct ldb_context *samdb,
1194 struct dnsserver_zone *zone)
1195 {
1196 int ret;
1197
1198 ret = ldb_transaction_start(samdb);
1199 if (ret != LDB_SUCCESS) {
1200 return WERR_INTERNAL_DB_ERROR;
1201 }
1202
1203 ret = dsdb_delete(samdb, zone->zone_dn, DSDB_TREE_DELETE);
1204 if (ret != LDB_SUCCESS) {
1205 ldb_transaction_cancel(samdb);
1206
1207 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
1208 return WERR_ACCESS_DENIED;
1209 }
1210 return WERR_INTERNAL_DB_ERROR;
1211 }
1212
1213 ret = ldb_transaction_commit(samdb);
1214 if (ret != LDB_SUCCESS) {
1215 return WERR_INTERNAL_DB_ERROR;
1216 }
1217
1218 return WERR_OK;
1219 }
1220