2 Unix SMB/CIFS implementation.
6 Copyright (C) Amitay Isaacs 2011
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.
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.
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/>.
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"
32 /* There are only 2 fixed partitions for DNS */
33 struct dnsserver_partition *dnsserver_db_enumerate_partitions(TALLOC_CTX *mem_ctx,
34 struct dnsserver_serverinfo *serverinfo,
35 struct ldb_context *samdb)
37 struct dnsserver_partition *partitions, *p;
41 /* Domain partition */
42 p = talloc_zero(mem_ctx, struct dnsserver_partition);
47 p->partition_dn = ldb_dn_new(p, samdb, serverinfo->pszDomainDirectoryPartition);
48 if (p->partition_dn == NULL) {
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;
56 DLIST_ADD_END(partitions, p, NULL);
58 /* Forest Partition */
59 p = talloc_zero(mem_ctx, struct dnsserver_partition);
64 p->partition_dn = ldb_dn_new(p, samdb, serverinfo->pszForestDirectoryPartition);
65 if (p->partition_dn == NULL) {
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;
73 DLIST_ADD_END(partitions, p, NULL);
83 /* Search for all dnsZone records */
84 struct dnsserver_zone *dnsserver_db_enumerate_zones(TALLOC_CTX *mem_ctx,
85 struct ldb_context *samdb,
86 struct dnsserver_partition *p)
89 const char * const attrs[] = {"name", NULL};
91 struct ldb_result *res;
92 struct dnsserver_zone *zones, *z;
95 tmp_ctx = talloc_new(mem_ctx);
96 if (tmp_ctx == NULL) {
100 dn = ldb_dn_copy(tmp_ctx, p->partition_dn);
104 if (!ldb_dn_add_child_fmt(dn, "CN=MicrosoftDNS")) {
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)));
117 for(i=0; i<res->count; i++) {
119 z = talloc_zero(mem_ctx, struct dnsserver_zone);
125 name = talloc_strdup(z,
126 ldb_msg_find_attr_as_string(res->msgs[i], "name", NULL));
127 if (strcmp(name, "RootDNSServers") == 0) {
129 z->name = talloc_strdup(z, ".");
133 z->zone_dn = talloc_steal(z, res->msgs[i]->dn);
135 DLIST_ADD_END(zones, z, NULL);
136 DEBUG(2, ("dnsserver: Found DNS zone %s\n", z->name));
142 talloc_free(tmp_ctx);
147 /* Find DNS partition information */
148 struct dnsserver_partition_info *dnsserver_db_partition_info(TALLOC_CTX *mem_ctx,
149 struct ldb_context *samdb,
150 struct dnsserver_partition *p)
152 const char * const attrs[] = { "instanceType", "msDs-masteredBy", NULL };
153 const char * const attrs_none[] = { NULL };
154 struct ldb_result *res;
155 struct ldb_message_element *el;
157 struct dnsserver_partition_info *partinfo;
158 int i, ret, instance_type;
161 tmp_ctx = talloc_new(mem_ctx);
162 if (tmp_ctx == NULL) {
166 partinfo = talloc_zero(mem_ctx, struct dnsserver_partition_info);
167 if (partinfo == NULL) {
168 talloc_free(tmp_ctx);
172 /* Search for the active replica and state */
173 ret = ldb_search(samdb, tmp_ctx, &res, p->partition_dn, LDB_SCOPE_BASE,
175 if (ret != LDB_SUCCESS || res->count != 1) {
179 /* Set the state of the partition */
180 instance_type = ldb_msg_find_attr_as_int(res->msgs[0], "instanceType", -1);
181 if (instance_type == -1) {
182 partinfo->dwState = DNS_DP_STATE_UNKNOWN;
183 } else if (instance_type & INSTANCE_TYPE_NC_COMING) {
184 partinfo->dwState = DNS_DP_STATE_REPL_INCOMING;
185 } else if (instance_type & INSTANCE_TYPE_NC_GOING) {
186 partinfo->dwState = DNS_DP_STATE_REPL_OUTGOING;
188 partinfo->dwState = DNS_DP_OKAY;
191 el = ldb_msg_find_element(res->msgs[0], "msDs-masteredBy");
193 partinfo->dwReplicaCount = 0;
194 partinfo->ReplicaArray = NULL;
196 partinfo->dwReplicaCount = el->num_values;
197 partinfo->ReplicaArray = talloc_zero_array(partinfo,
198 struct DNS_RPC_DP_REPLICA *,
200 if (partinfo->ReplicaArray == NULL) {
203 for (i=0; i<el->num_values; i++) {
204 partinfo->ReplicaArray[i] = talloc_zero(partinfo,
205 struct DNS_RPC_DP_REPLICA);
206 if (partinfo->ReplicaArray[i] == NULL) {
209 partinfo->ReplicaArray[i]->pszReplicaDn = talloc_strdup(
211 (const char *)el->values[i].data);
212 if (partinfo->ReplicaArray[i]->pszReplicaDn == NULL) {
219 /* Search for cross-reference object */
220 dn = ldb_dn_copy(tmp_ctx, ldb_get_config_basedn(samdb));
225 ret = ldb_search(samdb, tmp_ctx, &res, dn, LDB_SCOPE_DEFAULT, attrs_none,
226 "(nCName=%s)", ldb_dn_get_linearized(p->partition_dn));
227 if (ret != LDB_SUCCESS || res->count != 1) {
230 partinfo->pszCrDn = talloc_strdup(partinfo, ldb_dn_get_linearized(res->msgs[0]->dn));
231 if (partinfo->pszCrDn == NULL) {
236 talloc_free(tmp_ctx);
240 talloc_free(tmp_ctx);
241 talloc_free(partinfo);
246 static unsigned int dnsserver_update_soa(TALLOC_CTX *mem_ctx,
247 struct ldb_context *samdb,
248 struct dnsserver_zone *z)
250 const char * const attrs[] = { "dnsRecord", NULL };
251 struct ldb_result *res;
252 struct dnsp_DnssrvRpcRecord rec;
253 struct ldb_message_element *el;
254 enum ndr_err_code ndr_err;
255 int ret, i, serial = -1;
258 unix_to_nt_time(&t, time(NULL));
259 t /= 10*1000*1000; /* convert to seconds (NT time is in 100ns units) */
260 t /= 3600; /* convert to hours */
262 ret = ldb_search(samdb, mem_ctx, &res, z->zone_dn, LDB_SCOPE_ONELEVEL, attrs,
263 "(&(objectClass=dnsNode)(name=@))");
264 if (ret != LDB_SUCCESS || res->count == 0) {
268 el = ldb_msg_find_element(res->msgs[0], "dnsRecord");
273 for (i=0; i<el->num_values; i++) {
274 ndr_err = ndr_pull_struct_blob(&el->values[i], mem_ctx, &rec,
275 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
276 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
280 if (rec.wType == DNS_TYPE_SOA) {
281 serial = rec.data.soa.serial + 1;
282 rec.dwSerial = serial;
283 rec.dwTimeStamp = (uint32_t)t;
284 rec.data.soa.serial = serial;
286 ndr_err = ndr_push_struct_blob(&el->values[i], mem_ctx, &rec,
287 (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord);
288 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
296 el->flags = LDB_FLAG_MOD_REPLACE;
297 ret = ldb_modify(samdb, res->msgs[0]);
298 if (ret != LDB_SUCCESS) {
307 /* Add DNS record to the database */
308 static WERROR dnsserver_db_do_add_rec(TALLOC_CTX *mem_ctx,
309 struct ldb_context *samdb,
312 struct dnsp_DnssrvRpcRecord *rec)
314 struct ldb_message *msg;
317 enum ndr_err_code ndr_err;
320 msg = ldb_msg_new(mem_ctx);
321 W_ERROR_HAVE_NO_MEMORY(msg);
324 ret = ldb_msg_add_string(msg, "objectClass", "dnsNode");
325 if (ret != LDB_SUCCESS) {
329 if (num_rec > 0 && rec) {
330 for (i=0; i<num_rec; i++) {
331 ndr_err = ndr_push_struct_blob(&v, mem_ctx, &rec[i],
332 (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord);
333 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
334 return WERR_GENERAL_FAILURE;
337 ret = ldb_msg_add_value(msg, "dnsRecord", &v, NULL);
338 if (ret != LDB_SUCCESS) {
344 ret = ldb_add(samdb, msg);
345 if (ret != LDB_SUCCESS) {
346 return WERR_INTERNAL_DB_ERROR;
353 WERROR dnsserver_db_add_empty_node(TALLOC_CTX *mem_ctx,
354 struct ldb_context *samdb,
355 struct dnsserver_zone *z,
358 const char * const attrs[] = { "name", NULL };
359 struct ldb_result *res;
363 ret = ldb_search(samdb, mem_ctx, &res, z->zone_dn, LDB_SCOPE_BASE, attrs,
364 "(&(objectClass=dnsNode)(name=%s))", name);
365 if (ret != LDB_SUCCESS) {
366 return WERR_INTERNAL_DB_ERROR;
369 if (res->count > 0) {
371 return WERR_DNS_ERROR_RECORD_ALREADY_EXISTS;
374 dn = ldb_dn_copy(mem_ctx, z->zone_dn);
375 W_ERROR_HAVE_NO_MEMORY(dn);
377 if (!ldb_dn_add_child_fmt(dn, "DC=%s", name)) {
381 return dnsserver_db_do_add_rec(mem_ctx, samdb, dn, 0, NULL);
385 WERROR dnsserver_db_add_record(TALLOC_CTX *mem_ctx,
386 struct ldb_context *samdb,
387 struct dnsserver_zone *z,
389 struct DNS_RPC_RECORD *add_record)
391 const char * const attrs[] = { "dnsRecord", NULL };
392 struct ldb_result *res;
393 struct dnsp_DnssrvRpcRecord *rec;
394 struct ldb_message_element *el;
396 enum ndr_err_code ndr_err;
401 rec = dns_to_dnsp_copy(mem_ctx, add_record);
402 W_ERROR_HAVE_NO_MEMORY(rec);
404 serial = dnsserver_update_soa(mem_ctx, samdb, z);
406 return WERR_INTERNAL_DB_ERROR;
409 unix_to_nt_time(&t, time(NULL));
410 t /= 10*1000*1000; /* convert to seconds (NT time is in 100ns units) */
411 t /= 3600; /* convert to hours */
413 rec->dwSerial = serial;
414 rec->dwTimeStamp = t;
416 ret = ldb_search(samdb, mem_ctx, &res, z->zone_dn, LDB_SCOPE_ONELEVEL, attrs,
417 "(&(objectClass=dnsNode)(name=%s))", name);
418 if (ret != LDB_SUCCESS) {
419 return WERR_INTERNAL_DB_ERROR;
422 if (res->count == 0) {
423 dn = dnsserver_name_to_dn(mem_ctx, z, name);
424 W_ERROR_HAVE_NO_MEMORY(dn);
426 return dnsserver_db_do_add_rec(mem_ctx, samdb, dn, 1, rec);
429 el = ldb_msg_find_element(res->msgs[0], "dnsRecord");
431 ret = ldb_msg_add_empty(res->msgs[0], "dnsRecord", 0, &el);
432 if (ret != LDB_SUCCESS) {
437 for (i=0; i<el->num_values; i++) {
438 struct dnsp_DnssrvRpcRecord rec2;
440 ndr_err = ndr_pull_struct_blob(&el->values[i], mem_ctx, &rec2,
441 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
442 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
443 return WERR_GENERAL_FAILURE;
446 if (dns_record_match(rec, &rec2)) {
450 if (i < el->num_values) {
451 return WERR_DNS_ERROR_RECORD_ALREADY_EXISTS;
453 if (i == el->num_values) {
454 /* adding a new value */
455 el->values = talloc_realloc(el, el->values, struct ldb_val, el->num_values+1);
456 W_ERROR_HAVE_NO_MEMORY(el->values);
460 ndr_err = ndr_push_struct_blob(&el->values[i], mem_ctx, rec,
461 (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord);
462 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
463 return WERR_GENERAL_FAILURE;
466 el->flags = LDB_FLAG_MOD_REPLACE;
467 ret = ldb_modify(samdb, res->msgs[0]);
468 if (ret != LDB_SUCCESS) {
469 return WERR_INTERNAL_DB_ERROR;
475 WERROR dnsserver_db_update_record(TALLOC_CTX *mem_ctx,
476 struct ldb_context *samdb,
477 struct dnsserver_zone *z,
479 struct DNS_RPC_RECORD *add_record,
480 struct DNS_RPC_RECORD *del_record)
482 const char * const attrs[] = { "dnsRecord", NULL };
483 struct ldb_result *res;
484 struct dnsp_DnssrvRpcRecord *arec, *drec;
485 struct ldb_message_element *el;
486 enum ndr_err_code ndr_err;
491 serial = dnsserver_update_soa(mem_ctx, samdb, z);
493 return WERR_INTERNAL_DB_ERROR;
496 arec = dns_to_dnsp_copy(mem_ctx, add_record);
497 W_ERROR_HAVE_NO_MEMORY(arec);
499 drec = dns_to_dnsp_copy(mem_ctx, del_record);
500 W_ERROR_HAVE_NO_MEMORY(drec);
502 unix_to_nt_time(&t, time(NULL));
505 arec->dwSerial = serial;
506 arec->dwTimeStamp = t;
508 ret = ldb_search(samdb, mem_ctx, &res, z->zone_dn, LDB_SCOPE_ONELEVEL, attrs,
509 "(&(objectClass=dnsNode)(name=%s))", name);
510 if (ret != LDB_SUCCESS) {
511 return WERR_INTERNAL_DB_ERROR;
514 if (res->count == 0) {
515 return WERR_DNS_ERROR_RECORD_DOES_NOT_EXIST;
518 el = ldb_msg_find_element(res->msgs[0], "dnsRecord");
519 if (el == NULL || el->num_values == 0) {
520 return WERR_DNS_ERROR_RECORD_DOES_NOT_EXIST;
523 for (i=0; i<el->num_values; i++) {
524 struct dnsp_DnssrvRpcRecord rec2;
526 ndr_err = ndr_pull_struct_blob(&el->values[i], mem_ctx, &rec2,
527 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
528 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
529 return WERR_GENERAL_FAILURE;
532 if (dns_record_match(arec, &rec2)) {
536 if (i < el->num_values) {
537 return WERR_DNS_ERROR_RECORD_ALREADY_EXISTS;
541 for (i=0; i<el->num_values; i++) {
542 struct dnsp_DnssrvRpcRecord rec2;
544 ndr_err = ndr_pull_struct_blob(&el->values[i], mem_ctx, &rec2,
545 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
546 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
547 return WERR_GENERAL_FAILURE;
550 if (dns_record_match(drec, &rec2)) {
554 if (i == el->num_values) {
555 return WERR_DNS_ERROR_RECORD_DOES_NOT_EXIST;
558 ndr_err = ndr_push_struct_blob(&el->values[i], mem_ctx, arec,
559 (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord);
560 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
561 return WERR_GENERAL_FAILURE;
564 el->flags = LDB_FLAG_MOD_REPLACE;
565 ret = ldb_modify(samdb, res->msgs[0]);
566 if (ret != LDB_SUCCESS) {
567 return WERR_INTERNAL_DB_ERROR;
573 WERROR dnsserver_db_delete_record(TALLOC_CTX *mem_ctx,
574 struct ldb_context *samdb,
575 struct dnsserver_zone *z,
577 struct DNS_RPC_RECORD *del_record)
579 const char * const attrs[] = { "dnsRecord", NULL };
580 struct ldb_result *res;
581 struct dnsp_DnssrvRpcRecord *rec;
582 struct ldb_message_element *el;
583 enum ndr_err_code ndr_err;
587 serial = dnsserver_update_soa(mem_ctx, samdb, z);
589 return WERR_INTERNAL_DB_ERROR;
592 rec = dns_to_dnsp_copy(mem_ctx, del_record);
593 W_ERROR_HAVE_NO_MEMORY(rec);
595 ret = ldb_search(samdb, mem_ctx, &res, z->zone_dn, LDB_SCOPE_ONELEVEL, attrs,
596 "(&(objectClass=dnsNode)(name=%s))", name);
597 if (ret != LDB_SUCCESS) {
598 return WERR_INTERNAL_DB_ERROR;
601 if (res->count == 0) {
602 return WERR_DNS_ERROR_RECORD_DOES_NOT_EXIST;
605 el = ldb_msg_find_element(res->msgs[0], "dnsRecord");
606 if (el == NULL || el->num_values == 0) {
607 return WERR_DNS_ERROR_RECORD_DOES_NOT_EXIST;
610 for (i=0; i<el->num_values; i++) {
611 struct dnsp_DnssrvRpcRecord rec2;
613 ndr_err = ndr_pull_struct_blob(&el->values[i], mem_ctx, &rec2,
614 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
615 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
616 return WERR_GENERAL_FAILURE;
619 if (dns_record_match(rec, &rec2)) {
623 if (i == el->num_values) {
624 return WERR_DNS_ERROR_RECORD_DOES_NOT_EXIST;
626 if (i < el->num_values-1) {
627 memmove(&el->values[i], &el->values[i+1], sizeof(el->values[0])*((el->num_values-1)-i));
631 if (el->num_values == 0) {
632 ret = ldb_delete(samdb, res->msgs[0]->dn);
634 el->flags = LDB_FLAG_MOD_REPLACE;
635 ret = ldb_modify(samdb, res->msgs[0]);
637 if (ret != LDB_SUCCESS) {
638 return WERR_INTERNAL_DB_ERROR;
645 static bool dnsserver_db_msg_add_dnsproperty(TALLOC_CTX *mem_ctx,
646 struct ldb_message *msg,
647 struct dnsp_DnsProperty *prop)
649 DATA_BLOB *prop_blob;
650 enum ndr_err_code ndr_err;
653 prop_blob = talloc_zero(mem_ctx, DATA_BLOB);
654 if (prop_blob == NULL) return false;
656 ndr_err = ndr_push_struct_blob(prop_blob, mem_ctx, prop,
657 (ndr_push_flags_fn_t)ndr_push_dnsp_DnsProperty);
658 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
661 ret = ldb_msg_add_steal_value(msg, "dNSProperty", prop_blob);
662 if (ret != LDB_SUCCESS) {
669 /* Create dnsZone record to database and set security descriptor */
670 static WERROR dnsserver_db_do_create_zone(TALLOC_CTX *tmp_ctx,
671 struct ldb_context *samdb,
672 struct ldb_dn *zone_dn,
673 struct dnsserver_zone *z)
675 const char * const attrs[] = { "objectSID", NULL };
676 struct ldb_message *msg;
677 struct ldb_result *res;
678 struct ldb_message_element *el;
679 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";
681 struct dom_sid dnsadmins_sid;
682 const struct dom_sid *domain_sid;
683 struct security_descriptor *secdesc;
684 struct dnsp_DnsProperty *prop;
685 DATA_BLOB *sd_encoded;
686 enum ndr_err_code ndr_err;
689 /* Get DnsAdmins SID */
690 ret = ldb_search(samdb, tmp_ctx, &res, ldb_get_default_basedn(samdb),
691 LDB_SCOPE_DEFAULT, attrs, "(sAMAccountName=DnsAdmins)");
692 if (ret != LDB_SUCCESS || res->count != 1) {
693 return WERR_INTERNAL_DB_ERROR;
696 el = ldb_msg_find_element(res->msgs[0], "objectSID");
697 if (el == NULL || el->num_values != 1) {
698 return WERR_INTERNAL_DB_ERROR;
701 ndr_err = ndr_pull_struct_blob(&el->values[0], tmp_ctx, &dnsadmins_sid,
702 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
703 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
704 return WERR_INTERNAL_DB_ERROR;
707 /* create security descriptor with DnsAdmins GUID in sddl template */
708 sddl = talloc_asprintf(tmp_ctx, sddl_template,
709 dom_sid_string(tmp_ctx, &dnsadmins_sid));
715 domain_sid = samdb_domain_sid(samdb);
716 if (domain_sid == NULL) {
717 return WERR_INTERNAL_DB_ERROR;
720 secdesc = sddl_decode(tmp_ctx, sddl, domain_sid);
721 if (secdesc == NULL) {
722 return WERR_GENERAL_FAILURE;
725 msg = ldb_msg_new(tmp_ctx);
726 W_ERROR_HAVE_NO_MEMORY(msg);
729 ret = ldb_msg_add_string(msg, "objectClass", "dnsZone");
730 if (ret != LDB_SUCCESS) {
734 sd_encoded = talloc_zero(tmp_ctx, DATA_BLOB);
735 W_ERROR_HAVE_NO_MEMORY(sd_encoded);
737 ndr_err = ndr_push_struct_blob(sd_encoded, tmp_ctx, secdesc,
738 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
739 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
740 return WERR_GENERAL_FAILURE;
743 ret = ldb_msg_add_steal_value(msg, "nTSecurityDescriptor", sd_encoded);
744 if (ret != LDB_SUCCESS) {
748 /* dns zone Properties */
749 prop = talloc_zero(tmp_ctx, struct dnsp_DnsProperty);
750 W_ERROR_HAVE_NO_MEMORY(prop);
755 prop->id = DSPROPERTY_ZONE_TYPE;
756 prop->data.zone_type = z->zoneinfo->dwZoneType;
757 if (!dnsserver_db_msg_add_dnsproperty(tmp_ctx, msg, prop)) {
762 prop->id = DSPROPERTY_ZONE_ALLOW_UPDATE;
763 prop->data.allow_update_flag = z->zoneinfo->fAllowUpdate;
764 if (!dnsserver_db_msg_add_dnsproperty(tmp_ctx, msg, prop)) {
769 prop->id = DSPROPERTY_ZONE_SECURE_TIME;
770 prop->data.zone_secure_time = 0;
771 if (!dnsserver_db_msg_add_dnsproperty(tmp_ctx, msg, prop)) {
775 /* norefresh interval */
776 prop->id = DSPROPERTY_ZONE_NOREFRESH_INTERVAL;
777 prop->data.norefresh_hours = 168;
778 if (!dnsserver_db_msg_add_dnsproperty(tmp_ctx, msg, prop)) {
782 /* refresh interval */
783 prop->id = DSPROPERTY_ZONE_REFRESH_INTERVAL;
784 prop->data.refresh_hours = 168;
785 if (!dnsserver_db_msg_add_dnsproperty(tmp_ctx, msg, prop)) {
790 prop->id = DSPROPERTY_ZONE_AGING_STATE;
791 prop->data.aging_enabled = z->zoneinfo->fAging;
792 if (!dnsserver_db_msg_add_dnsproperty(tmp_ctx, msg, prop)) {
796 /* aging enabled time */
797 prop->id = DSPROPERTY_ZONE_AGING_ENABLED_TIME;
798 prop->data.next_scavenging_cycle_hours = 0;
799 if (!dnsserver_db_msg_add_dnsproperty(tmp_ctx, msg, prop)) {
805 ret = ldb_add(samdb, msg);
806 if (ret != LDB_SUCCESS) {
807 DEBUG(0, ("dnsserver: Failed to create zone (%s): %s\n",
808 z->name, ldb_errstring(samdb)));
809 return WERR_INTERNAL_DB_ERROR;
816 /* Create new dnsZone record and @ record (SOA + NS) */
817 WERROR dnsserver_db_create_zone(struct ldb_context *samdb,
818 struct dnsserver_partition *partitions,
819 struct dnsserver_zone *zone,
820 struct loadparm_context *lp_ctx)
822 struct dnsserver_partition *p;
823 bool in_forest = false;
827 struct dnsp_DnssrvRpcRecord *dns_rec;
829 char *tmpstr, *server_fqdn, *soa_email;
832 /* We only support primary zones for now */
833 if (zone->zoneinfo->dwZoneType != DNS_ZONE_TYPE_PRIMARY) {
834 return WERR_CALL_NOT_IMPLEMENTED;
837 /* Get the correct partition */
838 if (zone->partition->dwDpFlags & DNS_DP_FOREST_DEFAULT) {
841 for (p = partitions; p; p = p->next) {
842 if (in_forest == p->is_forest) {
847 return WERR_DNS_ERROR_DP_DOES_NOT_EXIST;
850 tmp_ctx = talloc_new(NULL);
851 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
853 dn = ldb_dn_copy(tmp_ctx, p->partition_dn);
854 W_ERROR_HAVE_NO_MEMORY_AND_FREE(dn, tmp_ctx);
856 if(!ldb_dn_add_child_fmt(dn, "DC=%s,CN=MicrosoftDNS", zone->name)) {
857 talloc_free(tmp_ctx);
861 /* Add dnsZone record */
862 status = dnsserver_db_do_create_zone(tmp_ctx, samdb, dn, zone);
863 if (!W_ERROR_IS_OK(status)) {
864 talloc_free(tmp_ctx);
868 if (!ldb_dn_add_child_fmt(dn, "DC=@")) {
869 talloc_free(tmp_ctx);
873 dns_rec = talloc_zero_array(tmp_ctx, struct dnsp_DnssrvRpcRecord, 2);
874 W_ERROR_HAVE_NO_MEMORY_AND_FREE(dns_rec, tmp_ctx);
876 tmpstr = talloc_asprintf(tmp_ctx, "%s.%s",
877 lpcfg_netbios_name(lp_ctx),
878 lpcfg_realm(lp_ctx));
879 W_ERROR_HAVE_NO_MEMORY_AND_FREE(tmpstr, tmp_ctx);
880 server_fqdn = strlower_talloc(tmp_ctx, tmpstr);
881 W_ERROR_HAVE_NO_MEMORY_AND_FREE(server_fqdn, tmp_ctx);
884 tmpstr = talloc_asprintf(tmp_ctx, "hostmaster.%s",
885 lpcfg_realm(lp_ctx));
886 W_ERROR_HAVE_NO_MEMORY_AND_FREE(tmpstr, tmp_ctx);
887 soa_email = strlower_talloc(tmp_ctx, tmpstr);
888 W_ERROR_HAVE_NO_MEMORY_AND_FREE(soa_email, tmp_ctx);
891 unix_to_nt_time(&t, time(NULL));
892 t /= 10*1000*1000; /* convert to seconds (NT time is in 100ns units) */
893 t /= 3600; /* convert to hours */
895 /* SOA Record - values same as defined in provision/sambadns.py */
901 soa.mname = server_fqdn;
902 soa.rname = soa_email;
904 dns_rec[0].wType = DNS_TYPE_SOA;
905 dns_rec[0].rank = DNS_RANK_ZONE;
906 dns_rec[0].dwSerial = soa.serial;
907 dns_rec[0].dwTtlSeconds = 3600;
908 dns_rec[0].dwTimeStamp = (uint32_t)t;
909 dns_rec[0].data.soa = soa;
912 dns_rec[1].wType = DNS_TYPE_NS;
913 dns_rec[1].rank = DNS_RANK_ZONE;
914 dns_rec[1].dwSerial = soa.serial;
915 dns_rec[1].dwTimeStamp = (uint32_t)t;
916 dns_rec[1].data.ns = server_fqdn;
919 status = dnsserver_db_do_add_rec(tmp_ctx, samdb, dn, 2, dns_rec);
921 talloc_free(tmp_ctx);
926 /* Delete dnsZone record and all DNS records in the zone */
927 WERROR dnsserver_db_delete_zone(struct ldb_context *samdb,
928 struct dnsserver_zone *zone)
932 ret = ldb_transaction_start(samdb);
933 if (ret != LDB_SUCCESS) {
934 return WERR_INTERNAL_DB_ERROR;
937 ret = dsdb_delete(samdb, zone->zone_dn, DSDB_TREE_DELETE);
938 if (ret != LDB_SUCCESS) {
939 ldb_transaction_cancel(samdb);
940 return WERR_INTERNAL_DB_ERROR;
943 ret = ldb_transaction_commit(samdb);
944 if (ret != LDB_SUCCESS) {
945 return WERR_INTERNAL_DB_ERROR;