From 7ad2367483e2eebfbfa991af494fdca892d8f28e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Jul 2014 17:55:57 +0200 Subject: [PATCH 01/29] s4:dns_server: handle WERR_DNS_ERROR_NAME_DOES_NOT_EXIST in werr_to_dns_err() Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam --- source4/dns_server/dns_utils.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source4/dns_server/dns_utils.c b/source4/dns_server/dns_utils.c index 72782cf..86f7e7c 100644 --- a/source4/dns_server/dns_utils.c +++ b/source4/dns_server/dns_utils.c @@ -43,6 +43,8 @@ uint8_t werr_to_dns_err(WERROR werr) return DNS_RCODE_SERVFAIL; } else if (W_ERROR_EQUAL(DNS_ERR(NAME_ERROR), werr)) { return DNS_RCODE_NXDOMAIN; + } else if (W_ERROR_EQUAL(WERR_DNS_ERROR_NAME_DOES_NOT_EXIST, werr)) { + return DNS_RCODE_NXDOMAIN; } else if (W_ERROR_EQUAL(DNS_ERR(NOT_IMPLEMENTED), werr)) { return DNS_RCODE_NOTIMP; } else if (W_ERROR_EQUAL(DNS_ERR(REFUSED), werr)) { -- 1.9.1 From 81bbbf16950b31149362c3a6debc17fb87799977 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 31 Jul 2014 08:19:50 +0200 Subject: [PATCH 02/29] s4:dns_server: map LDB_ERR_NO_SUCH_OBJECT to WERR_DNS_ERROR_NAME_DOES_NOT_EXIST This is the correct fix for commit 8b24c43b382740106474e26dec59e1419ba77306 and Bug: https://bugzilla.samba.org/show_bug.cgi?id=9559 With this change we have a consistent behavior between internal server and the bind dlz module. We keep a dangling LDAP object without dnsRecord attribute arround forever. This will be fixed in the following commits. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam --- source4/dns_server/dns_update.c | 21 ++++++++++++++++----- source4/dns_server/dns_utils.c | 17 ++++++++--------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/source4/dns_server/dns_update.c b/source4/dns_server/dns_update.c index 9edc40b..c439d8d 100644 --- a/source4/dns_server/dns_update.c +++ b/source4/dns_server/dns_update.c @@ -82,6 +82,9 @@ static WERROR check_one_prerequisite(struct dns_server *dns, /* */ werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount); + if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) { + return DNS_ERR(NAME_ERROR); + } W_ERROR_NOT_OK_RETURN(werror); if (acount == 0) { @@ -91,6 +94,9 @@ static WERROR check_one_prerequisite(struct dns_server *dns, /* */ werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount); + if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) { + return DNS_ERR(NXRRSET); + } if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) { return DNS_ERR(NXRRSET); } @@ -131,10 +137,11 @@ static WERROR check_one_prerequisite(struct dns_server *dns, /* */ werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount); + if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) { + werror = WERR_OK; + } if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) { werror = WERR_OK; - ans = NULL; - acount = 0; } for (i = 0; i < acount; i++) { @@ -163,6 +170,9 @@ static WERROR check_one_prerequisite(struct dns_server *dns, *final_result = false; werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount); + if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) { + return DNS_ERR(NXRRSET); + } if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) { return DNS_ERR(NXRRSET); } @@ -421,12 +431,13 @@ static WERROR handle_one_update(struct dns_server *dns, W_ERROR_NOT_OK_RETURN(werror); werror = dns_lookup_records(dns, mem_ctx, dn, &recs, &rcount); - if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) { - recs = NULL; - rcount = 0; + if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) { needs_add = true; werror = WERR_OK; } + if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) { + werror = WERR_OK; + } W_ERROR_NOT_OK_RETURN(werror); if (update->rr_class == zone->question_class) { diff --git a/source4/dns_server/dns_utils.c b/source4/dns_server/dns_utils.c index 86f7e7c..14ca2f4 100644 --- a/source4/dns_server/dns_utils.c +++ b/source4/dns_server/dns_utils.c @@ -194,8 +194,14 @@ WERROR dns_lookup_records(struct dns_server *dns, struct ldb_message *msg = NULL; struct dnsp_DnssrvRpcRecord *recs; + *records = NULL; + *rec_count = 0; + ret = dsdb_search_one(dns->samdb, mem_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "%s", "(objectClass=dnsNode)"); + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST; + } if (ret != LDB_SUCCESS) { /* TODO: we need to check if there's a glue record we need to * create a referral to */ @@ -204,8 +210,6 @@ WERROR dns_lookup_records(struct dns_server *dns, el = ldb_msg_find_element(msg, attrs[0]); if (el == NULL) { - *records = NULL; - *rec_count = 0; return DNS_ERR(NAME_ERROR); } @@ -278,13 +282,8 @@ WERROR dns_replace_records(struct dns_server *dns, if (needs_add) { return WERR_OK; } - /* No entries left, delete the dnsNode object */ - ret = ldb_delete(dns->samdb, msg->dn); - if (ret != LDB_SUCCESS) { - DEBUG(0, ("Deleting record failed; %d\n", ret)); - return DNS_ERR(SERVER_FAILURE); - } - return WERR_OK; + /* TODO: Delete object? */ + el->flags = LDB_FLAG_MOD_DELETE; } if (needs_add) { -- 1.9.1 From e83bbb37fec3d4cdf890cfe4d7e076ab88b15cde Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Jul 2014 08:01:11 +0200 Subject: [PATCH 03/29] s4:dns_server: split out a private 'dnsserver_common' library This will contain common code for the internal dns server, the dlz_bind9 module and the rpc dns management server. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam --- source4/dns_server/dns_server.h | 4 +- source4/dns_server/dns_utils.c | 33 ----------------- source4/dns_server/dnsserver_common.c | 69 +++++++++++++++++++++++++++++++++++ source4/dns_server/dnsserver_common.h | 28 ++++++++++++++ source4/dns_server/wscript_build | 8 +++- 5 files changed, 106 insertions(+), 36 deletions(-) create mode 100644 source4/dns_server/dnsserver_common.c create mode 100644 source4/dns_server/dnsserver_common.h diff --git a/source4/dns_server/dns_server.h b/source4/dns_server/dns_server.h index efe4db8..2459616 100644 --- a/source4/dns_server/dns_server.h +++ b/source4/dns_server/dns_server.h @@ -86,7 +86,6 @@ WERROR dns_server_process_update(struct dns_server *dns, struct dns_res_rec **updates, uint16_t *update_count, struct dns_res_rec **additional, uint16_t *arcount); -uint8_t werr_to_dns_err(WERROR werror); bool dns_name_match(const char *zone, const char *name, size_t *host_part_len); bool dns_name_equal(const char *name1, const char *name2); bool dns_records_match(struct dnsp_DnssrvRpcRecord *rec1, @@ -124,5 +123,6 @@ WERROR dns_sign_tsig(struct dns_server *dns, struct dns_name_packet *packet, uint16_t error); -#define DNS_ERR(err_str) WERR_DNS_ERROR_RCODE_##err_str +#include "source4/dns_server/dnsserver_common.h" + #endif /* __DNS_SERVER_H__ */ diff --git a/source4/dns_server/dns_utils.c b/source4/dns_server/dns_utils.c index 14ca2f4..461e58d 100644 --- a/source4/dns_server/dns_utils.c +++ b/source4/dns_server/dns_utils.c @@ -33,39 +33,6 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_DNS -uint8_t werr_to_dns_err(WERROR werr) -{ - if (W_ERROR_EQUAL(WERR_OK, werr)) { - return DNS_RCODE_OK; - } else if (W_ERROR_EQUAL(DNS_ERR(FORMAT_ERROR), werr)) { - return DNS_RCODE_FORMERR; - } else if (W_ERROR_EQUAL(DNS_ERR(SERVER_FAILURE), werr)) { - return DNS_RCODE_SERVFAIL; - } else if (W_ERROR_EQUAL(DNS_ERR(NAME_ERROR), werr)) { - return DNS_RCODE_NXDOMAIN; - } else if (W_ERROR_EQUAL(WERR_DNS_ERROR_NAME_DOES_NOT_EXIST, werr)) { - return DNS_RCODE_NXDOMAIN; - } else if (W_ERROR_EQUAL(DNS_ERR(NOT_IMPLEMENTED), werr)) { - return DNS_RCODE_NOTIMP; - } else if (W_ERROR_EQUAL(DNS_ERR(REFUSED), werr)) { - return DNS_RCODE_REFUSED; - } else if (W_ERROR_EQUAL(DNS_ERR(YXDOMAIN), werr)) { - return DNS_RCODE_YXDOMAIN; - } else if (W_ERROR_EQUAL(DNS_ERR(YXRRSET), werr)) { - return DNS_RCODE_YXRRSET; - } else if (W_ERROR_EQUAL(DNS_ERR(NXRRSET), werr)) { - return DNS_RCODE_NXRRSET; - } else if (W_ERROR_EQUAL(DNS_ERR(NOTAUTH), werr)) { - return DNS_RCODE_NOTAUTH; - } else if (W_ERROR_EQUAL(DNS_ERR(NOTZONE), werr)) { - return DNS_RCODE_NOTZONE; - } else if (W_ERROR_EQUAL(DNS_ERR(BADKEY), werr)) { - return DNS_RCODE_BADKEY; - } - DEBUG(5, ("No mapping exists for %s\n", win_errstr(werr))); - return DNS_RCODE_SERVFAIL; -} - bool dns_name_match(const char *zone, const char *name, size_t *host_part_len) { size_t zl = strlen(zone); diff --git a/source4/dns_server/dnsserver_common.c b/source4/dns_server/dnsserver_common.c new file mode 100644 index 0000000..67fa13c --- /dev/null +++ b/source4/dns_server/dnsserver_common.c @@ -0,0 +1,69 @@ +/* + Unix SMB/CIFS implementation. + + DNS server utils + + Copyright (C) 2010 Kai Blin + Copyright (C) 2014 Stefan Metzmacher + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "libcli/util/ntstatus.h" +#include "libcli/util/werror.h" +#include "librpc/ndr/libndr.h" +#include "librpc/gen_ndr/ndr_dns.h" +#include "librpc/gen_ndr/ndr_dnsp.h" +#include +#include "dsdb/samdb/samdb.h" +#include "dsdb/common/util.h" +#include "dns_server/dnsserver_common.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_DNS + +uint8_t werr_to_dns_err(WERROR werr) +{ + if (W_ERROR_EQUAL(WERR_OK, werr)) { + return DNS_RCODE_OK; + } else if (W_ERROR_EQUAL(DNS_ERR(FORMAT_ERROR), werr)) { + return DNS_RCODE_FORMERR; + } else if (W_ERROR_EQUAL(DNS_ERR(SERVER_FAILURE), werr)) { + return DNS_RCODE_SERVFAIL; + } else if (W_ERROR_EQUAL(DNS_ERR(NAME_ERROR), werr)) { + return DNS_RCODE_NXDOMAIN; + } else if (W_ERROR_EQUAL(WERR_DNS_ERROR_NAME_DOES_NOT_EXIST, werr)) { + return DNS_RCODE_NXDOMAIN; + } else if (W_ERROR_EQUAL(DNS_ERR(NOT_IMPLEMENTED), werr)) { + return DNS_RCODE_NOTIMP; + } else if (W_ERROR_EQUAL(DNS_ERR(REFUSED), werr)) { + return DNS_RCODE_REFUSED; + } else if (W_ERROR_EQUAL(DNS_ERR(YXDOMAIN), werr)) { + return DNS_RCODE_YXDOMAIN; + } else if (W_ERROR_EQUAL(DNS_ERR(YXRRSET), werr)) { + return DNS_RCODE_YXRRSET; + } else if (W_ERROR_EQUAL(DNS_ERR(NXRRSET), werr)) { + return DNS_RCODE_NXRRSET; + } else if (W_ERROR_EQUAL(DNS_ERR(NOTAUTH), werr)) { + return DNS_RCODE_NOTAUTH; + } else if (W_ERROR_EQUAL(DNS_ERR(NOTZONE), werr)) { + return DNS_RCODE_NOTZONE; + } else if (W_ERROR_EQUAL(DNS_ERR(BADKEY), werr)) { + return DNS_RCODE_BADKEY; + } + DEBUG(5, ("No mapping exists for %s\n", win_errstr(werr))); + return DNS_RCODE_SERVFAIL; +} + diff --git a/source4/dns_server/dnsserver_common.h b/source4/dns_server/dnsserver_common.h new file mode 100644 index 0000000..41febe2 --- /dev/null +++ b/source4/dns_server/dnsserver_common.h @@ -0,0 +1,28 @@ +/* + Unix SMB/CIFS implementation. + + DNS server utils + + Copyright (C) 2014 Stefan Metzmacher + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef __DNSSERVER_COMMON_H__ +#define __DNSSERVER_COMMON_H__ + +uint8_t werr_to_dns_err(WERROR werr); +#define DNS_ERR(err_str) WERR_DNS_ERROR_RCODE_##err_str + +#endif /* __DNSSERVER_COMMON_H__ */ diff --git a/source4/dns_server/wscript_build b/source4/dns_server/wscript_build index 280f8de..66e6b72 100644 --- a/source4/dns_server/wscript_build +++ b/source4/dns_server/wscript_build @@ -1,10 +1,16 @@ #!/usr/bin/env python +bld.SAMBA_LIBRARY('dnsserver_common', + source='dnsserver_common.c', + deps='samba-util errors ldbsamba clidns', + private_library=True, + ) + bld.SAMBA_MODULE('service_dns', source='dns_server.c dns_query.c dns_update.c dns_utils.c dns_crypto.c', subsystem='service', init_function='server_service_dns_init', - deps='samba-hostconfig LIBTSOCKET LIBSAMBA_TSOCKET ldbsamba clidns gensec auth samba_server_gensec', + deps='samba-hostconfig LIBTSOCKET LIBSAMBA_TSOCKET ldbsamba clidns gensec auth samba_server_gensec dnsserver_common', local_include=False, internal_module=False, enabled=bld.AD_DC_BUILD_IS_ENABLED() -- 1.9.1 From 22b39c0d2e244fdf7f187e551654e8fa5d3a558c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Jul 2014 08:24:10 +0200 Subject: [PATCH 04/29] s4:dns_server: split out dns_common_extract() and dns_common_lookup() Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam --- source4/dns_server/dns_utils.c | 45 +------------------- source4/dns_server/dnsserver_common.c | 77 +++++++++++++++++++++++++++++++++++ source4/dns_server/dnsserver_common.h | 13 ++++++ 3 files changed, 91 insertions(+), 44 deletions(-) diff --git a/source4/dns_server/dns_utils.c b/source4/dns_server/dns_utils.c index 461e58d..3bfa98b 100644 --- a/source4/dns_server/dns_utils.c +++ b/source4/dns_server/dns_utils.c @@ -154,50 +154,7 @@ WERROR dns_lookup_records(struct dns_server *dns, struct dnsp_DnssrvRpcRecord **records, uint16_t *rec_count) { - static const char * const attrs[] = { "dnsRecord", NULL}; - struct ldb_message_element *el; - uint16_t ri; - int ret; - struct ldb_message *msg = NULL; - struct dnsp_DnssrvRpcRecord *recs; - - *records = NULL; - *rec_count = 0; - - ret = dsdb_search_one(dns->samdb, mem_ctx, &msg, dn, - LDB_SCOPE_BASE, attrs, 0, "%s", "(objectClass=dnsNode)"); - if (ret == LDB_ERR_NO_SUCH_OBJECT) { - return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST; - } - if (ret != LDB_SUCCESS) { - /* TODO: we need to check if there's a glue record we need to - * create a referral to */ - return DNS_ERR(NAME_ERROR); - } - - el = ldb_msg_find_element(msg, attrs[0]); - if (el == NULL) { - return DNS_ERR(NAME_ERROR); - } - - recs = talloc_zero_array(mem_ctx, struct dnsp_DnssrvRpcRecord, el->num_values); - if (recs == NULL) { - return WERR_NOMEM; - } - for (ri = 0; ri < el->num_values; ri++) { - struct ldb_val *v = &el->values[ri]; - enum ndr_err_code ndr_err; - - ndr_err = ndr_pull_struct_blob(v, recs, &recs[ri], - (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - DEBUG(0, ("Failed to grab dnsp_DnssrvRpcRecord\n")); - return DNS_ERR(SERVER_FAILURE); - } - } - *records = recs; - *rec_count = el->num_values; - return WERR_OK; + return dns_common_lookup(dns->samdb, mem_ctx, dn, records, rec_count); } WERROR dns_replace_records(struct dns_server *dns, diff --git a/source4/dns_server/dnsserver_common.c b/source4/dns_server/dnsserver_common.c index 67fa13c..c1d08b2 100644 --- a/source4/dns_server/dnsserver_common.c +++ b/source4/dns_server/dnsserver_common.c @@ -67,3 +67,80 @@ uint8_t werr_to_dns_err(WERROR werr) return DNS_RCODE_SERVFAIL; } +WERROR dns_common_extract(const struct ldb_message_element *el, + TALLOC_CTX *mem_ctx, + struct dnsp_DnssrvRpcRecord **records, + uint16_t *num_records) +{ + uint16_t ri; + struct dnsp_DnssrvRpcRecord *recs; + + *records = NULL; + *num_records = 0; + + recs = talloc_zero_array(mem_ctx, struct dnsp_DnssrvRpcRecord, + el->num_values); + if (recs == NULL) { + return WERR_NOMEM; + } + for (ri = 0; ri < el->num_values; ri++) { + struct ldb_val *v = &el->values[ri]; + enum ndr_err_code ndr_err; + + ndr_err = ndr_pull_struct_blob(v, recs, &recs[ri], + (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + TALLOC_FREE(recs); + DEBUG(0, ("Failed to grab dnsp_DnssrvRpcRecord\n")); + return DNS_ERR(SERVER_FAILURE); + } + } + *records = recs; + *num_records = el->num_values; + return WERR_OK; +} + +WERROR dns_common_lookup(struct ldb_context *samdb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *dn, + struct dnsp_DnssrvRpcRecord **records, + uint16_t *num_records) +{ + static const char * const attrs[] = { + "dnsRecord", + NULL + }; + int ret; + WERROR werr; + struct ldb_message *msg = NULL; + struct ldb_message_element *el; + + *records = NULL; + *num_records = 0; + + ret = dsdb_search_one(samdb, mem_ctx, &msg, dn, + LDB_SCOPE_BASE, attrs, 0, + "(objectClass=dnsNode)"); + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST; + } + if (ret != LDB_SUCCESS) { + /* TODO: we need to check if there's a glue record we need to + * create a referral to */ + return DNS_ERR(NAME_ERROR); + } + + el = ldb_msg_find_element(msg, "dnsRecord"); + if (el == NULL) { + TALLOC_FREE(msg); + return DNS_ERR(NAME_ERROR); + } + + werr = dns_common_extract(el, mem_ctx, records, num_records); + TALLOC_FREE(msg); + if (!W_ERROR_IS_OK(werr)) { + return werr; + } + + return WERR_OK; +} diff --git a/source4/dns_server/dnsserver_common.h b/source4/dns_server/dnsserver_common.h index 41febe2..4731780 100644 --- a/source4/dns_server/dnsserver_common.h +++ b/source4/dns_server/dnsserver_common.h @@ -25,4 +25,17 @@ uint8_t werr_to_dns_err(WERROR werr); #define DNS_ERR(err_str) WERR_DNS_ERROR_RCODE_##err_str +struct ldb_message_element; + +WERROR dns_common_extract(const struct ldb_message_element *el, + TALLOC_CTX *mem_ctx, + struct dnsp_DnssrvRpcRecord **records, + uint16_t *num_records); + +WERROR dns_common_lookup(struct ldb_context *samdb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *dn, + struct dnsp_DnssrvRpcRecord **records, + uint16_t *num_records); + #endif /* __DNSSERVER_COMMON_H__ */ -- 1.9.1 From 2328ff69d84fee043df04ef5496b85e98807b5cd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 31 Jul 2014 11:32:02 +0200 Subject: [PATCH 05/29] s4:dns_server: remove const from dns_replace_records() All callers are find we the record array gets modified. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam --- source4/dns_server/dns_server.h | 2 +- source4/dns_server/dns_utils.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source4/dns_server/dns_server.h b/source4/dns_server/dns_server.h index 2459616..12ccc9b 100644 --- a/source4/dns_server/dns_server.h +++ b/source4/dns_server/dns_server.h @@ -101,7 +101,7 @@ WERROR dns_replace_records(struct dns_server *dns, TALLOC_CTX *mem_ctx, struct ldb_dn *dn, bool needs_add, - const struct dnsp_DnssrvRpcRecord *records, + struct dnsp_DnssrvRpcRecord *records, uint16_t rec_count); WERROR dns_name2dn(struct dns_server *dns, TALLOC_CTX *mem_ctx, diff --git a/source4/dns_server/dns_utils.c b/source4/dns_server/dns_utils.c index 3bfa98b..cf1adcc 100644 --- a/source4/dns_server/dns_utils.c +++ b/source4/dns_server/dns_utils.c @@ -161,7 +161,7 @@ WERROR dns_replace_records(struct dns_server *dns, TALLOC_CTX *mem_ctx, struct ldb_dn *dn, bool needs_add, - const struct dnsp_DnssrvRpcRecord *records, + struct dnsp_DnssrvRpcRecord *records, uint16_t rec_count) { struct ldb_message_element *el; -- 1.9.1 From d5c0ecea60476bd22235ccbbf79161b243bf0ab7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Jul 2014 18:27:56 +0200 Subject: [PATCH 06/29] s4:dns_server: split out dns_common_replace() Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam --- source4/dns_server/dns_update.c | 2 - source4/dns_server/dns_utils.c | 70 ++----------------------------- source4/dns_server/dnsserver_common.c | 78 +++++++++++++++++++++++++++++++++++ source4/dns_server/dnsserver_common.h | 8 ++++ 4 files changed, 90 insertions(+), 68 deletions(-) diff --git a/source4/dns_server/dns_update.c b/source4/dns_server/dns_update.c index c439d8d..a589d63 100644 --- a/source4/dns_server/dns_update.c +++ b/source4/dns_server/dns_update.c @@ -312,8 +312,6 @@ static WERROR dns_rr_to_dnsp(TALLOC_CTX *mem_ctx, r->wType = rrec->rr_type; r->dwTtlSeconds = rrec->ttl; r->rank = DNS_RANK_ZONE; - /* TODO: Autogenerate this somehow */ - r->dwSerial = 110; /* If we get QCLASS_ANY, we're done here */ if (rrec->rr_class == DNS_QCLASS_ANY) { diff --git a/source4/dns_server/dns_utils.c b/source4/dns_server/dns_utils.c index cf1adcc..c3a27fe 100644 --- a/source4/dns_server/dns_utils.c +++ b/source4/dns_server/dns_utils.c @@ -164,72 +164,10 @@ WERROR dns_replace_records(struct dns_server *dns, struct dnsp_DnssrvRpcRecord *records, uint16_t rec_count) { - struct ldb_message_element *el; - uint16_t i; - int ret; - struct ldb_message *msg = NULL; - - msg = ldb_msg_new(mem_ctx); - W_ERROR_HAVE_NO_MEMORY(msg); - - msg->dn = dn; - - ret = ldb_msg_add_empty(msg, "dnsRecord", LDB_FLAG_MOD_REPLACE, &el); - if (ret != LDB_SUCCESS) { - return DNS_ERR(SERVER_FAILURE); - } - - el->values = talloc_zero_array(el, struct ldb_val, rec_count); - if (rec_count > 0) { - W_ERROR_HAVE_NO_MEMORY(el->values); - } - - for (i = 0; i < rec_count; i++) { - static const struct dnsp_DnssrvRpcRecord zero; - struct ldb_val *v = &el->values[el->num_values]; - enum ndr_err_code ndr_err; - - if (memcmp(&records[i], &zero, sizeof(zero)) == 0) { - continue; - } - ndr_err = ndr_push_struct_blob(v, el->values, &records[i], - (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - DEBUG(0, ("Failed to grab dnsp_DnssrvRpcRecord\n")); - return DNS_ERR(SERVER_FAILURE); - } - el->num_values++; - } - - - if (el->num_values == 0) { - if (needs_add) { - return WERR_OK; - } - /* TODO: Delete object? */ - el->flags = LDB_FLAG_MOD_DELETE; - } - - if (needs_add) { - ret = ldb_msg_add_string(msg, "objectClass", "dnsNode"); - if (ret != LDB_SUCCESS) { - return DNS_ERR(SERVER_FAILURE); - } - - ret = ldb_add(dns->samdb, msg); - if (ret != LDB_SUCCESS) { - return DNS_ERR(SERVER_FAILURE); - } - - return WERR_OK; - } - - ret = ldb_modify(dns->samdb, msg); - if (ret != LDB_SUCCESS) { - return DNS_ERR(SERVER_FAILURE); - } - - return WERR_OK; + /* TODO: Autogenerate this somehow */ + uint32_t dwSerial = 110; + return dns_common_replace(dns->samdb, mem_ctx, dn, + needs_add, dwSerial, records, rec_count); } bool dns_authorative_for_zone(struct dns_server *dns, diff --git a/source4/dns_server/dnsserver_common.c b/source4/dns_server/dnsserver_common.c index c1d08b2..3a777e5 100644 --- a/source4/dns_server/dnsserver_common.c +++ b/source4/dns_server/dnsserver_common.c @@ -144,3 +144,81 @@ WERROR dns_common_lookup(struct ldb_context *samdb, return WERR_OK; } + +WERROR dns_common_replace(struct ldb_context *samdb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *dn, + bool needs_add, + uint32_t serial, + struct dnsp_DnssrvRpcRecord *records, + uint16_t rec_count) +{ + struct ldb_message_element *el; + uint16_t i; + int ret; + struct ldb_message *msg = NULL; + + msg = ldb_msg_new(mem_ctx); + W_ERROR_HAVE_NO_MEMORY(msg); + + msg->dn = dn; + + ret = ldb_msg_add_empty(msg, "dnsRecord", LDB_FLAG_MOD_REPLACE, &el); + if (ret != LDB_SUCCESS) { + return DNS_ERR(SERVER_FAILURE); + } + + el->values = talloc_zero_array(el, struct ldb_val, rec_count); + if (rec_count > 0) { + W_ERROR_HAVE_NO_MEMORY(el->values); + } + + for (i = 0; i < rec_count; i++) { + static const struct dnsp_DnssrvRpcRecord zero; + struct ldb_val *v = &el->values[el->num_values]; + enum ndr_err_code ndr_err; + + if (memcmp(&records[i], &zero, sizeof(zero)) == 0) { + continue; + } + + records[i].dwSerial = serial; + ndr_err = ndr_push_struct_blob(v, el->values, &records[i], + (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(0, ("Failed to push dnsp_DnssrvRpcRecord\n")); + return DNS_ERR(SERVER_FAILURE); + } + el->num_values++; + } + + if (needs_add) { + if (el->num_values == 0) { + return WERR_OK; + } + + ret = ldb_msg_add_string(msg, "objectClass", "dnsNode"); + if (ret != LDB_SUCCESS) { + return DNS_ERR(SERVER_FAILURE); + } + + ret = ldb_add(samdb, msg); + if (ret != LDB_SUCCESS) { + return DNS_ERR(SERVER_FAILURE); + } + + return WERR_OK; + } + + if (el->num_values == 0) { + el->flags = LDB_FLAG_MOD_DELETE; + } + + ret = ldb_modify(samdb, msg); + if (ret != LDB_SUCCESS) { + NTSTATUS nt = dsdb_ldb_err_to_ntstatus(ret); + return ntstatus_to_werror(nt); + } + + return WERR_OK; +} diff --git a/source4/dns_server/dnsserver_common.h b/source4/dns_server/dnsserver_common.h index 4731780..1117ad1 100644 --- a/source4/dns_server/dnsserver_common.h +++ b/source4/dns_server/dnsserver_common.h @@ -38,4 +38,12 @@ WERROR dns_common_lookup(struct ldb_context *samdb, struct dnsp_DnssrvRpcRecord **records, uint16_t *num_records); +WERROR dns_common_replace(struct ldb_context *samdb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *dn, + bool needs_add, + uint32_t serial, + struct dnsp_DnssrvRpcRecord *records, + uint16_t rec_count); + #endif /* __DNSSERVER_COMMON_H__ */ -- 1.9.1 From 722d05ec3075579a796f3f1ffe5e66c31918570b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 31 Jul 2014 09:32:00 +0200 Subject: [PATCH 07/29] s4:dns_server: use .wType = DNS_TYPE_TOMBSTONE instead of ZERO_STRUCT() The result is the same, but it is clearer. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam --- source4/dns_server/dns_update.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/source4/dns_server/dns_update.c b/source4/dns_server/dns_update.c index a589d63..4ff82b4 100644 --- a/source4/dns_server/dns_update.c +++ b/source4/dns_server/dns_update.c @@ -521,7 +521,9 @@ static WERROR handle_one_update(struct dns_server *dns, continue; } - ZERO_STRUCT(recs[i]); + recs[i] = (struct dnsp_DnssrvRpcRecord) { + .wType = DNS_TYPE_TOMBSTONE, + }; } werror = dns_replace_records(dns, mem_ctx, dn, @@ -570,12 +572,16 @@ static WERROR handle_one_update(struct dns_server *dns, continue; } - ZERO_STRUCT(recs[i]); + recs[i] = (struct dnsp_DnssrvRpcRecord) { + .wType = DNS_TYPE_TOMBSTONE, + }; } } else { for (i = 0; i < rcount; i++) { - ZERO_STRUCT(recs[i]); + recs[i] = (struct dnsp_DnssrvRpcRecord) { + .wType = DNS_TYPE_TOMBSTONE, + }; } } @@ -591,7 +597,9 @@ static WERROR handle_one_update(struct dns_server *dns, } for (i = 0; i < rcount; i++) { if (recs[i].wType == update->rr_type) { - ZERO_STRUCT(recs[i]); + recs[i] = (struct dnsp_DnssrvRpcRecord) { + .wType = DNS_TYPE_TOMBSTONE, + }; } } @@ -635,7 +643,9 @@ static WERROR handle_one_update(struct dns_server *dns, for (i = 0; i < rcount; i++) { if (dns_records_match(del_rec, &recs[i])) { - ZERO_STRUCT(recs[i]); + recs[i] = (struct dnsp_DnssrvRpcRecord) { + .wType = DNS_TYPE_TOMBSTONE, + }; } } -- 1.9.1 From dd6ef06b3afc39a62ee3038ab0653db545144070 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 31 Jul 2014 08:54:17 +0200 Subject: [PATCH 08/29] s4:dns_server: make sure dns_common_lookup() doesn't return tombstones Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam --- source4/dns_server/dns_utils.c | 3 +- source4/dns_server/dnsserver_common.c | 53 ++++++++++++++++++++++++++++++++--- source4/dns_server/dnsserver_common.h | 3 +- 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/source4/dns_server/dns_utils.c b/source4/dns_server/dns_utils.c index c3a27fe..c757c15 100644 --- a/source4/dns_server/dns_utils.c +++ b/source4/dns_server/dns_utils.c @@ -154,7 +154,8 @@ WERROR dns_lookup_records(struct dns_server *dns, struct dnsp_DnssrvRpcRecord **records, uint16_t *rec_count) { - return dns_common_lookup(dns->samdb, mem_ctx, dn, records, rec_count); + return dns_common_lookup(dns->samdb, mem_ctx, dn, + records, rec_count, NULL); } WERROR dns_replace_records(struct dns_server *dns, diff --git a/source4/dns_server/dnsserver_common.c b/source4/dns_server/dnsserver_common.c index 3a777e5..2866734 100644 --- a/source4/dns_server/dnsserver_common.c +++ b/source4/dns_server/dnsserver_common.c @@ -104,10 +104,12 @@ WERROR dns_common_lookup(struct ldb_context *samdb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn, struct dnsp_DnssrvRpcRecord **records, - uint16_t *num_records) + uint16_t *num_records, + bool *tombstoned) { static const char * const attrs[] = { "dnsRecord", + "dNSTombstoned", NULL }; int ret; @@ -118,9 +120,16 @@ WERROR dns_common_lookup(struct ldb_context *samdb, *records = NULL; *num_records = 0; - ret = dsdb_search_one(samdb, mem_ctx, &msg, dn, - LDB_SCOPE_BASE, attrs, 0, - "(objectClass=dnsNode)"); + if (tombstoned != NULL) { + *tombstoned = false; + ret = dsdb_search_one(samdb, mem_ctx, &msg, dn, + LDB_SCOPE_BASE, attrs, 0, + "(objectClass=dnsNode)"); + } else { + ret = dsdb_search_one(samdb, mem_ctx, &msg, dn, + LDB_SCOPE_BASE, attrs, 0, + "(&(objectClass=dnsNode)(!(dNSTombstoned=TRUE)))"); + } if (ret == LDB_ERR_NO_SUCH_OBJECT) { return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST; } @@ -130,9 +139,45 @@ WERROR dns_common_lookup(struct ldb_context *samdb, return DNS_ERR(NAME_ERROR); } + if (tombstoned != NULL) { + *tombstoned = ldb_msg_find_attr_as_bool(msg, + "dNSTombstoned", false); + } + el = ldb_msg_find_element(msg, "dnsRecord"); if (el == NULL) { TALLOC_FREE(msg); + if (tombstoned != NULL) { + struct dnsp_DnssrvRpcRecord *recs; + /* + * records produced by older Samba releases + * keep dnsNode objects without dnsRecord and + * without setting dNSTombstoned=TRUE. + * + * We just pretend they're tombstones. + */ + recs = talloc_array(mem_ctx, + struct dnsp_DnssrvRpcRecord, + 1); + if (recs == NULL) { + return WERR_NOMEM; + } + recs[0] = (struct dnsp_DnssrvRpcRecord) { + .wType = DNS_TYPE_TOMBSTONE, + /* + * A value of timestamp != 0 + * indicated that the object was already + * a tombstone, this will be used + * in dns_common_replace() + */ + .data.timestamp = 1, + }; + + *tombstoned = true; + *records = recs; + *num_records = 1; + return WERR_OK; + } return DNS_ERR(NAME_ERROR); } diff --git a/source4/dns_server/dnsserver_common.h b/source4/dns_server/dnsserver_common.h index 1117ad1..becd243 100644 --- a/source4/dns_server/dnsserver_common.h +++ b/source4/dns_server/dnsserver_common.h @@ -36,7 +36,8 @@ WERROR dns_common_lookup(struct ldb_context *samdb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn, struct dnsp_DnssrvRpcRecord **records, - uint16_t *num_records); + uint16_t *num_records, + bool *tombstoned); WERROR dns_common_replace(struct ldb_context *samdb, TALLOC_CTX *mem_ctx, -- 1.9.1 From d111b3ea697238238cce5ae0d6532fe03233cfe1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 31 Jul 2014 10:44:41 +0200 Subject: [PATCH 09/29] s4:dns_server: add DNS_TYPE_TOMBSTONE support to dns_common_replace() Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 Pair-Programmed-With: Michael Adam Signed-off-by: Stefan Metzmacher Signed-off-by: Michael Adam --- source4/dns_server/dnsserver_common.c | 81 +++++++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 4 deletions(-) diff --git a/source4/dns_server/dnsserver_common.c b/source4/dns_server/dnsserver_common.c index 2866734..c49d6ec 100644 --- a/source4/dns_server/dnsserver_common.c +++ b/source4/dns_server/dnsserver_common.c @@ -190,6 +190,22 @@ WERROR dns_common_lookup(struct ldb_context *samdb, return WERR_OK; } +static int rec_cmp(const struct dnsp_DnssrvRpcRecord *r1, + const struct dnsp_DnssrvRpcRecord *r2) +{ + if (r1->wType != r2->wType) { + /* + * The records are sorted with higher types first + */ + return r2->wType - r1->wType; + } + + /* + * Then we need to sort from the oldest to newest timestamp + */ + return r1->dwTimeStamp - r2->dwTimeStamp; +} + WERROR dns_common_replace(struct ldb_context *samdb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn, @@ -202,6 +218,8 @@ WERROR dns_common_replace(struct ldb_context *samdb, uint16_t i; int ret; struct ldb_message *msg = NULL; + bool was_tombstoned = false; + bool become_tombstoned = false; msg = ldb_msg_new(mem_ctx); W_ERROR_HAVE_NO_MEMORY(msg); @@ -213,17 +231,30 @@ WERROR dns_common_replace(struct ldb_context *samdb, return DNS_ERR(SERVER_FAILURE); } - el->values = talloc_zero_array(el, struct ldb_val, rec_count); + /* + * we have at least one value, + * which might be used for the tombstone marker + */ + el->values = talloc_zero_array(el, struct ldb_val, MAX(1, rec_count)); if (rec_count > 0) { W_ERROR_HAVE_NO_MEMORY(el->values); + + /* + * We store a sorted list with the high wType values first + * that's what windows does. It also simplifies the + * filtering of DNS_TYPE_TOMBSTONE records + */ + TYPESAFE_QSORT(records, rec_count, rec_cmp); } for (i = 0; i < rec_count; i++) { - static const struct dnsp_DnssrvRpcRecord zero; struct ldb_val *v = &el->values[el->num_values]; enum ndr_err_code ndr_err; - if (memcmp(&records[i], &zero, sizeof(zero)) == 0) { + if (records[i].wType == DNS_TYPE_TOMBSTONE) { + if (records[i].data.timestamp != 0) { + was_tombstoned = true; + } continue; } @@ -256,7 +287,49 @@ WERROR dns_common_replace(struct ldb_context *samdb, } if (el->num_values == 0) { - el->flags = LDB_FLAG_MOD_DELETE; + struct dnsp_DnssrvRpcRecord tbs; + struct ldb_val *v = &el->values[el->num_values]; + enum ndr_err_code ndr_err; + struct timeval tv; + + if (was_tombstoned) { + /* + * This is already a tombstoned object. + * Just leave it instead of updating the time stamp. + */ + return WERR_OK; + } + + tv = timeval_current(); + tbs = (struct dnsp_DnssrvRpcRecord) { + .wType = DNS_TYPE_TOMBSTONE, + .dwSerial = serial, + .data.timestamp = timeval_to_nttime(&tv), + }; + + ndr_err = ndr_push_struct_blob(v, el->values, &tbs, + (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(0, ("Failed to push dnsp_DnssrvRpcRecord\n")); + return DNS_ERR(SERVER_FAILURE); + } + el->num_values++; + + become_tombstoned = true; + } + + if (was_tombstoned || become_tombstoned) { + ret = ldb_msg_add_empty(msg, "dNSTombstoned", + LDB_FLAG_MOD_REPLACE, NULL); + if (ret != LDB_SUCCESS) { + return DNS_ERR(SERVER_FAILURE); + } + + ret = ldb_msg_add_fmt(msg, "dNSTombstoned", "%s", + become_tombstoned ? "TRUE" : "FALSE"); + if (ret != LDB_SUCCESS) { + return DNS_ERR(SERVER_FAILURE); + } } ret = ldb_modify(samdb, msg); -- 1.9.1 From 3267f4829b29f4b8f641d7e480b84bcbb09c5c33 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 31 Jul 2014 09:35:26 +0200 Subject: [PATCH 10/29] s4:dns_server: handle tombstones in handle_one_update() Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam --- source4/dns_server/dns_update.c | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/source4/dns_server/dns_update.c b/source4/dns_server/dns_update.c index 4ff82b4..04e7d9a 100644 --- a/source4/dns_server/dns_update.c +++ b/source4/dns_server/dns_update.c @@ -400,7 +400,9 @@ static WERROR handle_one_update(struct dns_server *dns, uint16_t rcount = 0; struct ldb_dn *dn; uint16_t i; + uint16_t first = 0; WERROR werror; + bool tombstoned = false; bool needs_add = false; DEBUG(2, ("Looking at record: \n")); @@ -428,23 +430,29 @@ static WERROR handle_one_update(struct dns_server *dns, werror = dns_name2dn(dns, mem_ctx, update->name, &dn); W_ERROR_NOT_OK_RETURN(werror); - werror = dns_lookup_records(dns, mem_ctx, dn, &recs, &rcount); + werror = dns_common_lookup(dns->samdb, mem_ctx, dn, + &recs, &rcount, &tombstoned); if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) { needs_add = true; werror = WERR_OK; } - if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) { - werror = WERR_OK; - } W_ERROR_NOT_OK_RETURN(werror); + if (tombstoned) { + /* + * we need to keep the existing tombstone record + * and ignore it + */ + first = rcount; + } + if (update->rr_class == zone->question_class) { if (update->rr_type == DNS_QTYPE_CNAME) { /* * If there is a record in the directory * that's not a CNAME, ignore update */ - for (i = 0; i < rcount; i++) { + for (i = first; i < rcount; i++) { if (recs[i].wType != DNS_TYPE_CNAME) { DEBUG(5, ("Skipping update\n")); return WERR_OK; @@ -457,13 +465,14 @@ static WERROR handle_one_update(struct dns_server *dns, * per name, so replace everything with the new CNAME */ - rcount = 1; + rcount = first; recs = talloc_realloc(mem_ctx, recs, - struct dnsp_DnssrvRpcRecord, rcount); + struct dnsp_DnssrvRpcRecord, rcount + 1); W_ERROR_HAVE_NO_MEMORY(recs); - werror = dns_rr_to_dnsp(recs, update, &recs[0]); + werror = dns_rr_to_dnsp(recs, update, &recs[rcount]); W_ERROR_NOT_OK_RETURN(werror); + rcount += 1; werror = dns_replace_records(dns, mem_ctx, dn, needs_add, recs, rcount); @@ -475,7 +484,7 @@ static WERROR handle_one_update(struct dns_server *dns, * If there is a CNAME record for this name, * ignore update */ - for (i = 0; i < rcount; i++) { + for (i = first; i < rcount; i++) { if (recs[i].wType == DNS_TYPE_CNAME) { DEBUG(5, ("Skipping update\n")); return WERR_OK; @@ -490,7 +499,7 @@ static WERROR handle_one_update(struct dns_server *dns, * serial number is smaller than existing SOA's, * ignore update */ - for (i = 0; i < rcount; i++) { + for (i = first; i < rcount; i++) { if (recs[i].wType == DNS_TYPE_SOA) { uint16_t n, o; @@ -540,7 +549,7 @@ static WERROR handle_one_update(struct dns_server *dns, werror = dns_rr_to_dnsp(recs, update, &recs[rcount]); W_ERROR_NOT_OK_RETURN(werror); - for (i = 0; i < rcount; i++) { + for (i = first; i < rcount; i++) { if (!dns_records_match(&recs[i], &recs[rcount])) { continue; } @@ -562,7 +571,7 @@ static WERROR handle_one_update(struct dns_server *dns, } else if (update->rr_class == DNS_QCLASS_ANY) { if (update->rr_type == DNS_QTYPE_ALL) { if (dns_name_equal(update->name, zone->name)) { - for (i = 0; i < rcount; i++) { + for (i = first; i < rcount; i++) { if (recs[i].wType == DNS_TYPE_SOA) { continue; @@ -578,7 +587,7 @@ static WERROR handle_one_update(struct dns_server *dns, } } else { - for (i = 0; i < rcount; i++) { + for (i = first; i < rcount; i++) { recs[i] = (struct dnsp_DnssrvRpcRecord) { .wType = DNS_TYPE_TOMBSTONE, }; @@ -595,7 +604,7 @@ static WERROR handle_one_update(struct dns_server *dns, return WERR_OK; } } - for (i = 0; i < rcount; i++) { + for (i = first; i < rcount; i++) { if (recs[i].wType == update->rr_type) { recs[i] = (struct dnsp_DnssrvRpcRecord) { .wType = DNS_TYPE_TOMBSTONE, @@ -624,7 +633,7 @@ static WERROR handle_one_update(struct dns_server *dns, werror = dns_rr_to_dnsp(ns_rec, update, ns_rec); W_ERROR_NOT_OK_RETURN(werror); - for (i = 0; i < rcount; i++) { + for (i = first; i < rcount; i++) { if (dns_records_match(ns_rec, &recs[i])) { found = true; break; @@ -641,7 +650,7 @@ static WERROR handle_one_update(struct dns_server *dns, werror = dns_rr_to_dnsp(del_rec, update, del_rec); W_ERROR_NOT_OK_RETURN(werror); - for (i = 0; i < rcount; i++) { + for (i = first; i < rcount; i++) { if (dns_records_match(del_rec, &recs[i])) { recs[i] = (struct dnsp_DnssrvRpcRecord) { .wType = DNS_TYPE_TOMBSTONE, -- 1.9.1 From 7358f49f7e26f83c049d47873b729613c988a145 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 27 Feb 2014 09:59:51 +0100 Subject: [PATCH 11/29] s4:dlz_bind9: avoid some compiler warnings Signed-off-by: Stefan Metzmacher --- source4/dns_server/dlz_bind9.c | 6 +++--- source4/dns_server/dlz_minimal.h | 2 +- source4/torture/dns/dlz_bind9.c | 7 ++++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c index 3ffb06b..092f255 100644 --- a/source4/dns_server/dlz_bind9.c +++ b/source4/dns_server/dlz_bind9.c @@ -466,7 +466,7 @@ static isc_result_t b9_putnamedrr(struct dlz_bind9_data *state, parse options */ static isc_result_t parse_options(struct dlz_bind9_data *state, - unsigned int argc, char *argv[], + unsigned int argc, const char **argv, struct b9_options *options) { int opt; @@ -477,7 +477,7 @@ static isc_result_t parse_options(struct dlz_bind9_data *state, { NULL } }; - pc = poptGetContext("dlz_bind9", argc, (const char **)argv, long_options, + pc = poptGetContext("dlz_bind9", argc, argv, long_options, POPT_CONTEXT_KEEP_FIRST); while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { @@ -571,7 +571,7 @@ static int dlz_state_debug_unregister(struct dlz_bind9_data *state) called to initialise the driver */ _PUBLIC_ isc_result_t dlz_create(const char *dlzname, - unsigned int argc, char *argv[], + unsigned int argc, const char **argv, void **dbdata, ...) { struct dlz_bind9_data *state; diff --git a/source4/dns_server/dlz_minimal.h b/source4/dns_server/dlz_minimal.h index 5262cbd..98fb34e 100644 --- a/source4/dns_server/dlz_minimal.h +++ b/source4/dns_server/dlz_minimal.h @@ -100,7 +100,7 @@ int dlz_version(unsigned int *flags); /* * dlz_create() is required for all DLZ external drivers. */ -isc_result_t dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata, ...); +isc_result_t dlz_create(const char *dlzname, unsigned int argc, const char **argv, void **dbdata, ...); /* * dlz_destroy() is optional, and will be called when the driver is diff --git a/source4/torture/dns/dlz_bind9.c b/source4/torture/dns/dlz_bind9.c index b7d6957..0ee2f19 100644 --- a/source4/torture/dns/dlz_bind9.c +++ b/source4/torture/dns/dlz_bind9.c @@ -61,7 +61,7 @@ static bool test_dlz_bind9_create(struct torture_context *tctx) NULL }; tctx_static = tctx; - torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, discard_const_p(char *, argv), &dbdata, + torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata, "log", dlz_bind9_log_wrapper, NULL), ISC_R_SUCCESS, "Failed to create samba_dlz"); @@ -109,7 +109,7 @@ static bool test_dlz_bind9_configure(struct torture_context *tctx) NULL }; tctx_static = tctx; - torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, discard_const_p(char *, argv), &dbdata, + torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata, "log", dlz_bind9_log_wrapper, "writeable_zone", dlz_bind9_writeable_zone_hook, NULL), ISC_R_SUCCESS, @@ -144,7 +144,7 @@ static bool test_dlz_bind9_gensec(struct torture_context *tctx, const char *mech NULL }; tctx_static = tctx; - torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, discard_const_p(char *, argv), &dbdata, + torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata, "log", dlz_bind9_log_wrapper, "writeable_zone", dlz_bind9_writeable_zone_hook, NULL), ISC_R_SUCCESS, @@ -216,6 +216,7 @@ static struct torture_suite *dlz_bind9_suite(TALLOC_CTX *ctx) /** * DNS torture module initialization */ +NTSTATUS torture_bind_dns_init(void); NTSTATUS torture_bind_dns_init(void) { struct torture_suite *suite; -- 1.9.1 From f2e24077ec77fc814a1b95b5455d0276cfbd1359 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Jul 2014 17:57:13 +0200 Subject: [PATCH 12/29] s4:dlz_bind9: do an early talloc_free(el_ctx) in dlz_allnodes() We don't have to keep everything arround while walking the whole zone. Signed-off-by: Stefan Metzmacher --- source4/dns_server/dlz_bind9.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c index 092f255..83b6070 100644 --- a/source4/dns_server/dlz_bind9.c +++ b/source4/dns_server/dlz_bind9.c @@ -987,6 +987,8 @@ _PUBLIC_ isc_result_t dlz_allnodes(const char *zone, void *dbdata, continue; } } + + talloc_free(el_ctx); } talloc_free(tmp_ctx); -- 1.9.1 From 12521a84a1db66516bb2dbda7e4ce67f47ab4c2b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Jul 2014 08:40:32 +0200 Subject: [PATCH 13/29] s4:dlz_bind9: let dlz_bind9 use dns_common_lookup() for name lookup Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 Signed-off-by: Stefan Metzmacher --- source4/dns_server/dlz_bind9.c | 68 +++++++++++----------------------------- source4/dns_server/wscript_build | 6 ++-- 2 files changed, 21 insertions(+), 53 deletions(-) diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c index 83b6070..402de15 100644 --- a/source4/dns_server/dlz_bind9.c +++ b/source4/dns_server/dlz_bind9.c @@ -38,7 +38,7 @@ #include "lib/cmdline/popt_common.h" #include "lib/util/dlinklist.h" #include "dlz_minimal.h" - +#include "dns_server/dnsserver_common.h" struct b9_options { const char *url; @@ -808,11 +808,10 @@ static isc_result_t dlz_lookup_types(struct dlz_bind9_data *state, const char **types) { TALLOC_CTX *tmp_ctx = talloc_new(state); - const char *attrs[] = { "dnsRecord", NULL }; - int ret = LDB_SUCCESS, i; - struct ldb_result *res; - struct ldb_message_element *el; struct ldb_dn *dn; + WERROR werr = WERR_DNS_ERROR_NAME_DOES_NOT_EXIST; + struct dnsp_DnssrvRpcRecord *records = NULL; + uint16_t num_records = 0, i; for (i=0; zone_prefixes[i]; i++) { dn = ldb_dn_copy(tmp_ctx, ldb_get_default_basedn(state->samdb)); @@ -826,38 +825,21 @@ static isc_result_t dlz_lookup_types(struct dlz_bind9_data *state, return ISC_R_NOMEMORY; } - ret = ldb_search(state->samdb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, - attrs, "objectClass=dnsNode"); - if (ret == LDB_SUCCESS) { + werr = dns_common_lookup(state->samdb, tmp_ctx, dn, + &records, &num_records, NULL); + if (W_ERROR_IS_OK(werr)) { break; } } - if (ret != LDB_SUCCESS || res->count == 0) { + if (!W_ERROR_IS_OK(werr)) { talloc_free(tmp_ctx); return ISC_R_NOTFOUND; } - el = ldb_msg_find_element(res->msgs[0], "dnsRecord"); - if (el == NULL || el->num_values == 0) { - talloc_free(tmp_ctx); - return ISC_R_NOTFOUND; - } - - for (i=0; inum_values; i++) { - struct dnsp_DnssrvRpcRecord rec; - enum ndr_err_code ndr_err; + for (i=0; i < num_records; i++) { isc_result_t result; - ndr_err = ndr_pull_struct_blob(&el->values[i], tmp_ctx, &rec, - (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s", - ldb_dn_get_linearized(dn)); - talloc_free(tmp_ctx); - return ISC_R_FAILURE; - } - - result = b9_putrr(state, lookup, &rec, types); + result = b9_putrr(state, lookup, &records[i], types); if (result != ISC_R_SUCCESS) { talloc_free(tmp_ctx); return result; @@ -1066,39 +1048,25 @@ _PUBLIC_ void dlz_closeversion(const char *zone, isc_boolean_t commit, */ static bool b9_has_soa(struct dlz_bind9_data *state, struct ldb_dn *dn, const char *zone) { - const char *attrs[] = { "dnsRecord", NULL }; - struct ldb_result *res; - struct ldb_message_element *el; TALLOC_CTX *tmp_ctx = talloc_new(state); - int ret, i; + WERROR werr; + struct dnsp_DnssrvRpcRecord *records = NULL; + uint16_t num_records = 0, i; if (!ldb_dn_add_child_fmt(dn, "DC=@,DC=%s", zone)) { talloc_free(tmp_ctx); return false; } - ret = ldb_search(state->samdb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, - attrs, "objectClass=dnsNode"); - if (ret != LDB_SUCCESS) { - talloc_free(tmp_ctx); - return false; - } - - el = ldb_msg_find_element(res->msgs[0], "dnsRecord"); - if (el == NULL) { + werr = dns_common_lookup(state->samdb, tmp_ctx, dn, + &records, &num_records, NULL); + if (!W_ERROR_IS_OK(werr)) { talloc_free(tmp_ctx); return false; } - for (i=0; inum_values; i++) { - struct dnsp_DnssrvRpcRecord rec; - enum ndr_err_code ndr_err; - ndr_err = ndr_pull_struct_blob(&el->values[i], tmp_ctx, &rec, - (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - continue; - } - if (rec.wType == DNS_TYPE_SOA) { + for (i=0; i < num_records; i++) { + if (records[i].wType == DNS_TYPE_SOA) { talloc_free(tmp_ctx); return true; } diff --git a/source4/dns_server/wscript_build b/source4/dns_server/wscript_build index 66e6b72..a92ab67 100644 --- a/source4/dns_server/wscript_build +++ b/source4/dns_server/wscript_build @@ -24,7 +24,7 @@ bld.SAMBA_LIBRARY('dlz_bind9', link_name='modules/bind9/dlz_bind9.so', realname='dlz_bind9.so', install_path='${MODULESDIR}/bind9', - deps='samba-hostconfig samdb-common gensec popt', + deps='samba-hostconfig samdb-common gensec popt dnsserver_common', enabled=bld.AD_DC_BUILD_IS_ENABLED()) bld.SAMBA_LIBRARY('dlz_bind9_9', @@ -34,12 +34,12 @@ bld.SAMBA_LIBRARY('dlz_bind9_9', link_name='modules/bind9/dlz_bind9_9.so', realname='dlz_bind9_9.so', install_path='${MODULESDIR}/bind9', - deps='samba-hostconfig samdb-common gensec popt', + deps='samba-hostconfig samdb-common gensec popt dnsserver_common', enabled=bld.AD_DC_BUILD_IS_ENABLED()) bld.SAMBA_LIBRARY('dlz_bind9_for_torture', source='dlz_bind9.c', cflags='-DBIND_VERSION_9_8', private_library=True, - deps='samba-hostconfig samdb-common gensec popt', + deps='samba-hostconfig samdb-common gensec popt dnsserver_common', enabled=bld.AD_DC_BUILD_IS_ENABLED()) -- 1.9.1 From b6b4b1964958a7e669cb3682780f2c522507db83 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Jul 2014 17:59:08 +0200 Subject: [PATCH 14/29] s4:dlz_bind9: let dlz_bind9 use dns_common_extract() Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 Signed-off-by: Stefan Metzmacher --- source4/dns_server/dlz_bind9.c | 118 +++++++++++++++++++++-------------------- 1 file changed, 61 insertions(+), 57 deletions(-) diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c index 402de15..0431307 100644 --- a/source4/dns_server/dlz_bind9.c +++ b/source4/dns_server/dlz_bind9.c @@ -918,6 +918,9 @@ _PUBLIC_ isc_result_t dlz_allnodes(const char *zone, void *dbdata, TALLOC_CTX *el_ctx = talloc_new(tmp_ctx); const char *rdn, *name; const struct ldb_val *v; + WERROR werr; + struct dnsp_DnssrvRpcRecord *recs = NULL; + uint16_t num_recs = 0; el = ldb_msg_find_element(res->msgs[i], "dnsRecord"); if (el == NULL || el->num_values == 0) { @@ -951,20 +954,18 @@ _PUBLIC_ isc_result_t dlz_allnodes(const char *zone, void *dbdata, return ISC_R_NOMEMORY; } - for (j=0; jnum_values; j++) { - struct dnsp_DnssrvRpcRecord rec; - enum ndr_err_code ndr_err; - isc_result_t result; + werr = dns_common_extract(el, el_ctx, &recs, &num_recs); + if (!W_ERROR_IS_OK(werr)) { + state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s, %s", + ldb_dn_get_linearized(dn), win_errstr(werr)); + talloc_free(el_ctx); + continue; + } - ndr_err = ndr_pull_struct_blob(&el->values[j], el_ctx, &rec, - (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s", - ldb_dn_get_linearized(dn)); - continue; - } + for (j=0; j < num_recs; j++) { + isc_result_t result; - result = b9_putnamedrr(state, allnodes, name, &rec); + result = b9_putnamedrr(state, allnodes, name, &recs[i]); if (result != ISC_R_SUCCESS) { continue; } @@ -1521,8 +1522,11 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo const char *attrs[] = { "dnsRecord", NULL }; int ret, i; struct ldb_message_element *el; + struct dnsp_DnssrvRpcRecord *recs = NULL; + uint16_t num_recs = 0; enum ndr_err_code ndr_err; NTTIME t; + WERROR werr; if (state->transaction_token != (void*)version) { state->log(ISC_LOG_INFO, "samba_dlz: bad transaction version"); @@ -1582,22 +1586,19 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo } } + werr = dns_common_extract(el, rec, &recs, &num_recs); + if (!W_ERROR_IS_OK(werr)) { + state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s, %s", + ldb_dn_get_linearized(dn), win_errstr(werr)); + talloc_free(rec); + return ISC_R_FAILURE; + } + /* there are existing records. We need to see if this will * replace a record or add to it */ - for (i=0; inum_values; i++) { - struct dnsp_DnssrvRpcRecord rec2; - - ndr_err = ndr_pull_struct_blob(&el->values[i], rec, &rec2, - (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s", - ldb_dn_get_linearized(dn)); - talloc_free(rec); - return ISC_R_FAILURE; - } - - if (b9_record_match(state, rec, &rec2)) { + for (i=0; i < num_recs; i++) { + if (b9_record_match(state, rec, &recs[i])) { break; } } @@ -1656,7 +1657,9 @@ _PUBLIC_ isc_result_t dlz_subrdataset(const char *name, const char *rdatastr, vo const char *attrs[] = { "dnsRecord", NULL }; int ret, i; struct ldb_message_element *el; - enum ndr_err_code ndr_err; + struct dnsp_DnssrvRpcRecord *recs = NULL; + uint16_t num_recs = 0; + WERROR werr; if (state->transaction_token != (void*)version) { state->log(ISC_LOG_ERROR, "samba_dlz: bad transaction version"); @@ -1698,19 +1701,16 @@ _PUBLIC_ isc_result_t dlz_subrdataset(const char *name, const char *rdatastr, vo return ISC_R_FAILURE; } - for (i=0; inum_values; i++) { - struct dnsp_DnssrvRpcRecord rec2; - - ndr_err = ndr_pull_struct_blob(&el->values[i], rec, &rec2, - (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s", - ldb_dn_get_linearized(dn)); - talloc_free(rec); - return ISC_R_FAILURE; - } + werr = dns_common_extract(el, rec, &recs, &num_recs); + if (!W_ERROR_IS_OK(werr)) { + state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s, %s", + ldb_dn_get_linearized(dn), win_errstr(werr)); + talloc_free(rec); + return ISC_R_FAILURE; + } - if (b9_record_match(state, rec, &rec2)) { + for (i=0; i < num_recs; i++) { + if (b9_record_match(state, rec, &recs[i])) { break; } } @@ -1762,11 +1762,15 @@ _PUBLIC_ isc_result_t dlz_delrdataset(const char *name, const char *type, void * isc_result_t result; struct ldb_result *res; const char *attrs[] = { "dnsRecord", NULL }; - int ret, i; + int ret; struct ldb_message_element *el; - enum ndr_err_code ndr_err; + int vi = 0; enum dns_record_type dns_type; bool found = false; + struct dnsp_DnssrvRpcRecord *recs = NULL; + uint16_t num_recs = 0; + uint16_t ri = 0; + WERROR werr; if (state->transaction_token != (void*)version) { state->log(ISC_LOG_ERROR, "samba_dlz: bad transaction version"); @@ -1802,27 +1806,27 @@ _PUBLIC_ isc_result_t dlz_delrdataset(const char *name, const char *type, void * return ISC_R_NOTFOUND; } - for (i=0; inum_values; i++) { - struct dnsp_DnssrvRpcRecord rec2; + werr = dns_common_extract(el, tmp_ctx, &recs, &num_recs); + if (!W_ERROR_IS_OK(werr)) { + state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s, %s", + ldb_dn_get_linearized(dn), win_errstr(werr)); + talloc_free(tmp_ctx); + return ISC_R_FAILURE; + } - ndr_err = ndr_pull_struct_blob(&el->values[i], tmp_ctx, &rec2, - (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s", - ldb_dn_get_linearized(dn)); - talloc_free(tmp_ctx); - return ISC_R_FAILURE; + for (ri=0; ri < num_recs; ri++) { + if (dns_type != recs[ri].wType) { + vi += 1; + continue; } - if (dns_type == rec2.wType) { - if (i < el->num_values-1) { - memmove(&el->values[i], &el->values[i+1], - sizeof(el->values[0])*((el->num_values-1)-i)); - } - el->num_values--; - i--; - found = true; + found = true; + + if (vi < el->num_values-1) { + memmove(&el->values[vi], &el->values[vi+1], + sizeof(el->values[0])*((el->num_values-1)-vi)); } + el->num_values--; } if (!found) { -- 1.9.1 From ab4276e364b6fefa04f0295dcbf66c3568afb857 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Jul 2014 18:51:39 +0200 Subject: [PATCH 15/29] s4:dlz_bind9: let dlz_bind9 use dns_common_replace() Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 Signed-off-by: Stefan Metzmacher --- source4/dns_server/dlz_bind9.c | 129 ++++++++++++++++------------------------- 1 file changed, 49 insertions(+), 80 deletions(-) diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c index 0431307..a4f2228 100644 --- a/source4/dns_server/dlz_bind9.c +++ b/source4/dns_server/dlz_bind9.c @@ -1355,32 +1355,15 @@ static isc_result_t b9_add_record(struct dlz_bind9_data *state, const char *name struct ldb_dn *dn, struct dnsp_DnssrvRpcRecord *rec) { - struct ldb_message *msg; - enum ndr_err_code ndr_err; - struct ldb_val v; - int ret; - - msg = ldb_msg_new(rec); - if (msg == NULL) { - return ISC_R_NOMEMORY; - } - msg->dn = dn; - ret = ldb_msg_add_string(msg, "objectClass", "dnsNode"); - if (ret != LDB_SUCCESS) { - return ISC_R_FAILURE; - } - - ndr_err = ndr_push_struct_blob(&v, rec, rec, (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return ISC_R_FAILURE; - } - ret = ldb_msg_add_value(msg, "dnsRecord", &v, NULL); - if (ret != LDB_SUCCESS) { - return ISC_R_FAILURE; - } + WERROR werr; - ret = ldb_add(state->samdb, msg); - if (ret != LDB_SUCCESS) { + werr = dns_common_replace(state->samdb, rec, dn, + true,/* needs_add */ + state->soa_serial, + rec, 1); + if (!W_ERROR_IS_OK(werr)) { + state->log(ISC_LOG_ERROR, "samba_dlz: failed to add %s - %s", + ldb_dn_get_linearized(dn), win_errstr(werr)); return ISC_R_FAILURE; } @@ -1524,7 +1507,6 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo struct ldb_message_element *el; struct dnsp_DnssrvRpcRecord *recs = NULL; uint16_t num_recs = 0; - enum ndr_err_code ndr_err; NTTIME t; WERROR werr; @@ -1543,7 +1525,6 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo t /= 3600; /* convert to hours */ rec->rank = DNS_RANK_ZONE; - rec->dwSerial = state->soa_serial; rec->dwTimeStamp = (uint32_t)t; if (!b9_parse(state, rdatastr, rec)) { @@ -1602,25 +1583,26 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo break; } } - if (i == el->num_values) { + if (i == UINT16_MAX) { + state->log(ISC_LOG_ERROR, "samba_dlz: failed to already %u dnsRecord values for %s", + i, ldb_dn_get_linearized(dn)); + talloc_free(rec); + return ISC_R_FAILURE; + } + + if (i == num_recs) { /* adding a new value */ - el->values = talloc_realloc(el, el->values, struct ldb_val, el->num_values+1); - if (el->values == NULL) { + recs = talloc_realloc(rec, recs, + struct dnsp_DnssrvRpcRecord, + num_recs + 1); + if (recs == NULL) { talloc_free(rec); return ISC_R_NOMEMORY; } - el->num_values++; - } - - ndr_err = ndr_push_struct_blob(&el->values[i], rec, rec, - (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - state->log(ISC_LOG_ERROR, "samba_dlz: failed to push dnsRecord for %s", - ldb_dn_get_linearized(dn)); - talloc_free(rec); - return ISC_R_FAILURE; + num_recs++; } + recs[i] = *rec; if (!b9_set_session_info(state, name)) { talloc_free(rec); @@ -1628,12 +1610,14 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo } /* modify the record */ - el->flags = LDB_FLAG_MOD_REPLACE; - ret = ldb_modify(state->samdb, res->msgs[0]); + werr = dns_common_replace(state->samdb, rec, dn, + false,/* needs_add */ + state->soa_serial, + recs, num_recs); b9_reset_session_info(state); - if (ret != LDB_SUCCESS) { + if (!W_ERROR_IS_OK(werr)) { state->log(ISC_LOG_ERROR, "samba_dlz: failed to modify %s - %s", - ldb_dn_get_linearized(dn), ldb_errstring(state->samdb)); + ldb_dn_get_linearized(dn), win_errstr(werr)); talloc_free(rec); return ISC_R_FAILURE; } @@ -1711,35 +1695,27 @@ _PUBLIC_ isc_result_t dlz_subrdataset(const char *name, const char *rdatastr, vo for (i=0; i < num_recs; i++) { if (b9_record_match(state, rec, &recs[i])) { + recs[i] = (struct dnsp_DnssrvRpcRecord) { + .wType = DNS_TYPE_TOMBSTONE, + }; break; } } - if (i == el->num_values) { - talloc_free(rec); - return ISC_R_NOTFOUND; - } - - if (i < el->num_values-1) { - memmove(&el->values[i], &el->values[i+1], sizeof(el->values[0])*((el->num_values-1)-i)); - } - el->num_values--; if (!b9_set_session_info(state, name)) { talloc_free(rec); return ISC_R_FAILURE; } - if (el->num_values == 0) { - el->flags = LDB_FLAG_MOD_DELETE; - } else { - el->flags = LDB_FLAG_MOD_REPLACE; - } - ret = ldb_modify(state->samdb, res->msgs[0]); - + /* modify the record */ + werr = dns_common_replace(state->samdb, rec, dn, + false,/* needs_add */ + state->soa_serial, + recs, num_recs); b9_reset_session_info(state); - if (ret != LDB_SUCCESS) { + if (!W_ERROR_IS_OK(werr)) { state->log(ISC_LOG_ERROR, "samba_dlz: failed to modify %s - %s", - ldb_dn_get_linearized(dn), ldb_errstring(state->samdb)); + ldb_dn_get_linearized(dn), win_errstr(werr)); talloc_free(rec); return ISC_R_FAILURE; } @@ -1764,7 +1740,6 @@ _PUBLIC_ isc_result_t dlz_delrdataset(const char *name, const char *type, void * const char *attrs[] = { "dnsRecord", NULL }; int ret; struct ldb_message_element *el; - int vi = 0; enum dns_record_type dns_type; bool found = false; struct dnsp_DnssrvRpcRecord *recs = NULL; @@ -1816,17 +1791,13 @@ _PUBLIC_ isc_result_t dlz_delrdataset(const char *name, const char *type, void * for (ri=0; ri < num_recs; ri++) { if (dns_type != recs[ri].wType) { - vi += 1; continue; } found = true; - - if (vi < el->num_values-1) { - memmove(&el->values[vi], &el->values[vi+1], - sizeof(el->values[0])*((el->num_values-1)-vi)); - } - el->num_values--; + recs[ri] = (struct dnsp_DnssrvRpcRecord) { + .wType = DNS_TYPE_TOMBSTONE, + }; } if (!found) { @@ -1839,17 +1810,15 @@ _PUBLIC_ isc_result_t dlz_delrdataset(const char *name, const char *type, void * return ISC_R_FAILURE; } - if (el->num_values == 0) { - el->flags = LDB_FLAG_MOD_DELETE; - } else { - el->flags = LDB_FLAG_MOD_REPLACE; - } - ret = ldb_modify(state->samdb, res->msgs[0]); - + /* modify the record */ + werr = dns_common_replace(state->samdb, tmp_ctx, dn, + false,/* needs_add */ + state->soa_serial, + recs, num_recs); b9_reset_session_info(state); - if (ret != LDB_SUCCESS) { - state->log(ISC_LOG_ERROR, "samba_dlz: failed to delete type %s in %s - %s", - type, ldb_dn_get_linearized(dn), ldb_errstring(state->samdb)); + if (!W_ERROR_IS_OK(werr)) { + state->log(ISC_LOG_ERROR, "samba_dlz: failed to modify %s - %s", + ldb_dn_get_linearized(dn), win_errstr(werr)); talloc_free(tmp_ctx); return ISC_R_FAILURE; } -- 1.9.1 From d9954137f2c4d32793411f16061f26b6baeb0d76 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Jul 2014 20:12:08 +0200 Subject: [PATCH 16/29] s4:dlz_bind9: let dlz_bind9 use dns_common_lookup() before removing records Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 Signed-off-by: Stefan Metzmacher --- source4/dns_server/dlz_bind9.c | 53 ++++++------------------------------------ 1 file changed, 7 insertions(+), 46 deletions(-) diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c index a4f2228..a0c42d1 100644 --- a/source4/dns_server/dlz_bind9.c +++ b/source4/dns_server/dlz_bind9.c @@ -1637,12 +1637,9 @@ _PUBLIC_ isc_result_t dlz_subrdataset(const char *name, const char *rdatastr, vo struct dnsp_DnssrvRpcRecord *rec; struct ldb_dn *dn; isc_result_t result; - struct ldb_result *res; - const char *attrs[] = { "dnsRecord", NULL }; - int ret, i; - struct ldb_message_element *el; struct dnsp_DnssrvRpcRecord *recs = NULL; uint16_t num_recs = 0; + uint16_t i; WERROR werr; if (state->transaction_token != (void*)version) { @@ -1669,28 +1666,11 @@ _PUBLIC_ isc_result_t dlz_subrdataset(const char *name, const char *rdatastr, vo } /* get the existing records */ - ret = ldb_search(state->samdb, rec, &res, dn, LDB_SCOPE_BASE, attrs, "objectClass=dnsNode"); - if (ret == LDB_ERR_NO_SUCH_OBJECT) { - talloc_free(rec); - return ISC_R_NOTFOUND; - } - - /* there are existing records. We need to see if any match - */ - el = ldb_msg_find_element(res->msgs[0], "dnsRecord"); - if (el == NULL || el->num_values == 0) { - state->log(ISC_LOG_ERROR, "samba_dlz: no dnsRecord attribute for %s", - ldb_dn_get_linearized(dn)); - talloc_free(rec); - return ISC_R_FAILURE; - } - - werr = dns_common_extract(el, rec, &recs, &num_recs); + werr = dns_common_lookup(state->samdb, rec, dn, + &recs, &num_recs, NULL); if (!W_ERROR_IS_OK(werr)) { - state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s, %s", - ldb_dn_get_linearized(dn), win_errstr(werr)); talloc_free(rec); - return ISC_R_FAILURE; + return ISC_R_NOTFOUND; } for (i=0; i < num_recs; i++) { @@ -1736,10 +1716,6 @@ _PUBLIC_ isc_result_t dlz_delrdataset(const char *name, const char *type, void * TALLOC_CTX *tmp_ctx; struct ldb_dn *dn; isc_result_t result; - struct ldb_result *res; - const char *attrs[] = { "dnsRecord", NULL }; - int ret; - struct ldb_message_element *el; enum dns_record_type dns_type; bool found = false; struct dnsp_DnssrvRpcRecord *recs = NULL; @@ -1767,26 +1743,11 @@ _PUBLIC_ isc_result_t dlz_delrdataset(const char *name, const char *type, void * } /* get the existing records */ - ret = ldb_search(state->samdb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, attrs, "objectClass=dnsNode"); - if (ret == LDB_ERR_NO_SUCH_OBJECT) { - talloc_free(tmp_ctx); - return ISC_R_NOTFOUND; - } - - /* there are existing records. We need to see if any match the type - */ - el = ldb_msg_find_element(res->msgs[0], "dnsRecord"); - if (el == NULL || el->num_values == 0) { - talloc_free(tmp_ctx); - return ISC_R_NOTFOUND; - } - - werr = dns_common_extract(el, tmp_ctx, &recs, &num_recs); + werr = dns_common_lookup(state->samdb, tmp_ctx, dn, + &recs, &num_recs, NULL); if (!W_ERROR_IS_OK(werr)) { - state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s, %s", - ldb_dn_get_linearized(dn), win_errstr(werr)); talloc_free(tmp_ctx); - return ISC_R_FAILURE; + return ISC_R_NOTFOUND; } for (ri=0; ri < num_recs; ri++) { -- 1.9.1 From 23c6105338a111ce09ccb5b01b29bdb8ce7c401e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 31 Jul 2014 09:30:16 +0200 Subject: [PATCH 17/29] s4:dlz_bind9: let dlz_bind9 use dns_common_lookup() before add/modify Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 Signed-off-by: Stefan Metzmacher --- source4/dns_server/dlz_bind9.c | 77 ++++++++++++------------------------------ 1 file changed, 21 insertions(+), 56 deletions(-) diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c index a0c42d1..93db40e 100644 --- a/source4/dns_server/dlz_bind9.c +++ b/source4/dns_server/dlz_bind9.c @@ -1347,29 +1347,6 @@ _PUBLIC_ isc_boolean_t dlz_ssumatch(const char *signer, const char *name, const return ISC_TRUE; } - -/* - add a new record - */ -static isc_result_t b9_add_record(struct dlz_bind9_data *state, const char *name, - struct ldb_dn *dn, - struct dnsp_DnssrvRpcRecord *rec) -{ - WERROR werr; - - werr = dns_common_replace(state->samdb, rec, dn, - true,/* needs_add */ - state->soa_serial, - rec, 1); - if (!W_ERROR_IS_OK(werr)) { - state->log(ISC_LOG_ERROR, "samba_dlz: failed to add %s - %s", - ldb_dn_get_linearized(dn), win_errstr(werr)); - return ISC_R_FAILURE; - } - - return ISC_R_SUCCESS; -} - /* see if two DNS names are the same */ @@ -1501,12 +1478,12 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo struct dnsp_DnssrvRpcRecord *rec; struct ldb_dn *dn; isc_result_t result; - struct ldb_result *res; - const char *attrs[] = { "dnsRecord", NULL }; - int ret, i; - struct ldb_message_element *el; + bool tombstoned = false; + bool needs_add = false; struct dnsp_DnssrvRpcRecord *recs = NULL; uint16_t num_recs = 0; + uint16_t first = 0; + uint16_t i; NTTIME t; WERROR werr; @@ -1541,33 +1518,12 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo } /* get any existing records */ - ret = ldb_search(state->samdb, rec, &res, dn, LDB_SCOPE_BASE, attrs, "objectClass=dnsNode"); - if (ret == LDB_ERR_NO_SUCH_OBJECT) { - if (!b9_set_session_info(state, name)) { - talloc_free(rec); - return ISC_R_FAILURE; - } - result = b9_add_record(state, name, dn, rec); - b9_reset_session_info(state); - talloc_free(rec); - if (result == ISC_R_SUCCESS) { - state->log(ISC_LOG_INFO, "samba_dlz: added %s %s", name, rdatastr); - } - return result; - } - - el = ldb_msg_find_element(res->msgs[0], "dnsRecord"); - if (el == NULL) { - ret = ldb_msg_add_empty(res->msgs[0], "dnsRecord", LDB_FLAG_MOD_ADD, &el); - if (ret != LDB_SUCCESS) { - state->log(ISC_LOG_ERROR, "samba_dlz: failed to add dnsRecord for %s", - ldb_dn_get_linearized(dn)); - talloc_free(rec); - return ISC_R_FAILURE; - } + werr = dns_common_lookup(state->samdb, rec, dn, + &recs, &num_recs, &tombstoned); + if (W_ERROR_EQUAL(werr, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) { + needs_add = true; + werr = WERR_OK; } - - werr = dns_common_extract(el, rec, &recs, &num_recs); if (!W_ERROR_IS_OK(werr)) { state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s, %s", ldb_dn_get_linearized(dn), win_errstr(werr)); @@ -1575,10 +1531,18 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo return ISC_R_FAILURE; } + if (tombstoned) { + /* + * we need to keep the existing tombstone record + * and ignore it + */ + first = num_recs; + } + /* there are existing records. We need to see if this will * replace a record or add to it */ - for (i=0; i < num_recs; i++) { + for (i=first; i < num_recs; i++) { if (b9_record_match(state, rec, &recs[i])) { break; } @@ -1611,12 +1575,13 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo /* modify the record */ werr = dns_common_replace(state->samdb, rec, dn, - false,/* needs_add */ + needs_add, state->soa_serial, recs, num_recs); b9_reset_session_info(state); if (!W_ERROR_IS_OK(werr)) { - state->log(ISC_LOG_ERROR, "samba_dlz: failed to modify %s - %s", + state->log(ISC_LOG_ERROR, "samba_dlz: failed to %s %s - %s", + needs_add ? "add" : "modify", ldb_dn_get_linearized(dn), win_errstr(werr)); talloc_free(rec); return ISC_R_FAILURE; -- 1.9.1 From 77af72ca249eebac5698b94f8b70653d01d9c6ab Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Jul 2014 07:25:08 +0200 Subject: [PATCH 18/29] libcli/dns: add AAAA support to dns_hosts_file.c Signed-off-by: Stefan Metzmacher --- libcli/dns/dns_hosts_file.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/libcli/dns/dns_hosts_file.c b/libcli/dns/dns_hosts_file.c index 94d1d97..5be5fca 100644 --- a/libcli/dns/dns_hosts_file.c +++ b/libcli/dns/dns_hosts_file.c @@ -88,9 +88,14 @@ static bool getdns_hosts_fileent(TALLOC_CTX *ctx, XFILE *fp, char **pp_name, cha if (next_token_talloc(ctx, &ptr, &name_type, NULL)) ++count; + if (count == 0) { + continue; + } if (next_token_talloc(ctx, &ptr, &name, NULL)) ++count; - if (name_type && strcasecmp(name_type, "A") == 0) { + if ((strcasecmp(name_type, "A") == 0) || + (strcasecmp(name_type, "AAAA") == 0)) + { if (next_token_talloc(ctx, &ptr, &ip, NULL)) ++count; } else if (name_type && strcasecmp(name_type, "SRV") == 0) { @@ -105,9 +110,11 @@ static bool getdns_hosts_fileent(TALLOC_CTX *ctx, XFILE *fp, char **pp_name, cha if (count <= 0) continue; - if (strcasecmp(name_type, "A") == 0) { + if ((strcasecmp(name_type, "A") == 0) || + (strcasecmp(name_type, "AAAA") == 0)) + { if (count != 3) { - DEBUG(0,("getdns_hosts_fileent: Ill formed hosts A record [%s]\n", + DEBUG(0,("getdns_hosts_fileent: Ill formed hosts A[AAA] record [%s]\n", line)); continue; } @@ -215,7 +222,7 @@ static NTSTATUS resolve_dns_hosts_file_as_dns_rr_recurse(const char *dns_hosts_f DEBUG(3,("resolve_dns_hosts: (%d) " "Attempting %s dns_hosts lookup for name %s\n", - level, srv_lookup ? "SRV" : "A", name)); + level, srv_lookup ? "SRV" : "A[AAA]", name)); fp = startdns_hosts_file(dns_hosts_file); @@ -278,7 +285,9 @@ static NTSTATUS resolve_dns_hosts_file_as_dns_rr_recurse(const char *dns_hosts_f mem_ctx, return_rr, return_count); talloc_free(ip_list_ctx); return status; - } else if (strcasecmp(name_type, "A") == 0) { + } else if ((strcasecmp(name_type, "A") == 0) || + (strcasecmp(name_type, "AAAA") == 0)) + { if (*return_count == 0) { /* We are happy to keep looking for other possible A record matches */ rr = talloc_zero(ip_list_ctx, @@ -405,11 +414,11 @@ NTSTATUS resolve_dns_hosts_file_as_dns_rr(const char *dns_hosts_file, if (NT_STATUS_IS_OK(status)) { DEBUG(3,("resolve_dns_hosts (dns_rr): " "Found %d %s result records for for name %s\n", - *return_count, srv_lookup ? "SRV" : "A", name)); + *return_count, srv_lookup ? "SRV" : "A[AAA]", name)); } else { DEBUG(3,("resolve_dns_hosts (dns_rr): " "failed to obtain %s result records for for name %s: %s\n", - srv_lookup ? "SRV" : "A", name, nt_errstr(status))); + srv_lookup ? "SRV" : "A[AAA]", name, nt_errstr(status))); } return status; } -- 1.9.1 From 0c509221ad1cb24524e98ff27fe442b3e0f1ebd8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Jul 2014 07:25:08 +0200 Subject: [PATCH 19/29] libcli/dns: ignore NS entries in dns_hosts_file.c at a higher log level for now Signed-off-by: Stefan Metzmacher --- libcli/dns/dns_hosts_file.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libcli/dns/dns_hosts_file.c b/libcli/dns/dns_hosts_file.c index 5be5fca..4b1bc53 100644 --- a/libcli/dns/dns_hosts_file.c +++ b/libcli/dns/dns_hosts_file.c @@ -106,6 +106,9 @@ static bool getdns_hosts_fileent(TALLOC_CTX *ctx, XFILE *fp, char **pp_name, cha } else if (name_type && strcasecmp(name_type, "CNAME") == 0) { if (next_token_talloc(ctx, &ptr, &next_name, NULL)) ++count; + } else if (name_type && strcasecmp(name_type, "NS") == 0) { + if (next_token_talloc(ctx, &ptr, &next_name, NULL)) + ++count; } if (count <= 0) continue; @@ -155,6 +158,15 @@ static bool getdns_hosts_fileent(TALLOC_CTX *ctx, XFILE *fp, char **pp_name, cha if (!*pp_next_name) { return false; } + } else if (strcasecmp(name_type, "NS") == 0) { + if (count != 3) { + DEBUG(0,("getdns_hosts_fileent: Ill formed hosts NS record [%s]\n", + line)); + continue; + } + DEBUG(4, ("getdns_hosts_fileent: NS entry: %s %s %s\n", + name_type, name, next_name)); + continue; } else { DEBUG(0,("getdns_hosts_fileent: unknown type %s\n", name_type)); continue; -- 1.9.1 From 8772d57a6d62186f4f14b5ab43944dfdb2d8f7f1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 19 Jun 2014 17:21:16 +0200 Subject: [PATCH 20/29] selftest: export _IPV6 environment variables Signed-off-by: Stefan Metzmacher --- selftest/README | 1 + selftest/selftest.pl | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/selftest/README b/selftest/README index c23d730..d9ad020 100644 --- a/selftest/README +++ b/selftest/README @@ -89,6 +89,7 @@ The environments are currently available include * REALM: Realm name * SERVER: DC host name * SERVER_IP: DC IPv4 address + * SERVER_IPV6: DC IPv6 address * NETBIOSNAME: DC NetBIOS name * NETIOSALIAS: DC NetBIOS alias diff --git a/selftest/selftest.pl b/selftest/selftest.pl index fde8451..8342bfe 100755 --- a/selftest/selftest.pl +++ b/selftest/selftest.pl @@ -707,35 +707,41 @@ my @exported_envvars = ( # domain controller stuff "DC_SERVER", "DC_SERVER_IP", + "DC_SERVER_IPV6", "DC_NETBIOSNAME", "DC_NETBIOSALIAS", # domain member "MEMBER_SERVER", "MEMBER_SERVER_IP", + "MEMBER_SERVER_IPV6", "MEMBER_NETBIOSNAME", "MEMBER_NETBIOSALIAS", # rpc proxy controller stuff "RPC_PROXY_SERVER", "RPC_PROXY_SERVER_IP", + "RPC_PROXY_SERVER_IPV6", "RPC_PROXY_NETBIOSNAME", "RPC_PROXY_NETBIOSALIAS", # domain controller stuff for Vampired DC "VAMPIRE_DC_SERVER", "VAMPIRE_DC_SERVER_IP", + "VAMPIRE_DC_SERVER_IPV6", "VAMPIRE_DC_NETBIOSNAME", "VAMPIRE_DC_NETBIOSALIAS", "PROMOTED_DC_SERVER", "PROMOTED_DC_SERVER_IP", + "PROMOTED_DC_SERVER_IPV6", "PROMOTED_DC_NETBIOSNAME", "PROMOTED_DC_NETBIOSALIAS", # server stuff "SERVER", "SERVER_IP", + "SERVER_IPV6", "NETBIOSNAME", "NETBIOSALIAS", -- 1.9.1 From 184d075515e7c18d8f244f0202b1c2121b0093d5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 19 Jun 2014 17:21:16 +0200 Subject: [PATCH 21/29] selftest/Samba4: also bind to ipv6 Signed-off-by: Stefan Metzmacher --- selftest/target/Samba4.pm | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index ec0f439..9ddb80a 100755 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -536,7 +536,8 @@ sub provision_raw_prepare($$$$$$$$$$) $ctx->{tlsdir} = "$ctx->{privatedir}/tls"; $ctx->{ipv4} = "127.0.0.$swiface"; - $ctx->{interfaces} = "$ctx->{ipv4}/8"; + $ctx->{ipv6} = sprintf("fd00:0000:0000:0000:0000:0000:5357:5f%02x", $swiface); + $ctx->{interfaces} = "$ctx->{ipv4}/8 $ctx->{ipv6}/64"; push(@{$ctx->{directories}}, $ctx->{privatedir}); push(@{$ctx->{directories}}, $ctx->{etcdir}); @@ -702,8 +703,8 @@ $ctx->{unix_name}:x:$ctx->{unix_gid}: my $hostname = lc($ctx->{hostname}); open(HOSTS, ">>$ctx->{nsswrap_hosts}"); - print HOSTS "$ctx->{ipv4} ${hostname}.samba.example.com ${hostname} -"; + print HOSTS "$ctx->{ipv4} ${hostname}.samba.example.com ${hostname}\n"; + print HOSTS "$ctx->{ipv6} ${hostname}.samba.example.com ${hostname}\n"; close(HOSTS); my $configuration = "--configfile=$ctx->{smb_conf}"; @@ -725,6 +726,7 @@ $ctx->{unix_name}:x:$ctx->{unix_gid}: PIDDIR => $ctx->{piddir}, SERVER => $ctx->{hostname}, SERVER_IP => $ctx->{ipv4}, + SERVER_IPV6 => $ctx->{ipv6}, NETBIOSNAME => $ctx->{netbiosname}, DOMAIN => $ctx->{domain}, USERNAME => $ctx->{username}, @@ -972,12 +974,14 @@ rpc_server:tcpip = no $ret->{MEMBER_SERVER} = $ret->{SERVER}; $ret->{MEMBER_SERVER_IP} = $ret->{SERVER_IP}; + $ret->{MEMBER_SERVER_IPV6} = $ret->{SERVER_IPV6}; $ret->{MEMBER_NETBIOSNAME} = $ret->{NETBIOSNAME}; $ret->{MEMBER_USERNAME} = $ret->{USERNAME}; $ret->{MEMBER_PASSWORD} = $ret->{PASSWORD}; $ret->{DC_SERVER} = $dcvars->{DC_SERVER}; $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP}; + $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6}; $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME}; $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME}; $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD}; @@ -1066,12 +1070,14 @@ sub provision_rpc_proxy($$$) $ret->{RPC_PROXY_SERVER} = $ret->{SERVER}; $ret->{RPC_PROXY_SERVER_IP} = $ret->{SERVER_IP}; + $ret->{RPC_PROXY_SERVER_IPV6} = $ret->{SERVER_IPV6}; $ret->{RPC_PROXY_NETBIOSNAME} = $ret->{NETBIOSNAME}; $ret->{RPC_PROXY_USERNAME} = $ret->{USERNAME}; $ret->{RPC_PROXY_PASSWORD} = $ret->{PASSWORD}; $ret->{DC_SERVER} = $dcvars->{DC_SERVER}; $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP}; + $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6}; $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME}; $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME}; $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD}; @@ -1142,10 +1148,12 @@ sub provision_promoted_dc($$$) $ret->{PROMOTED_DC_SERVER} = $ret->{SERVER}; $ret->{PROMOTED_DC_SERVER_IP} = $ret->{SERVER_IP}; + $ret->{PROMOTED_DC_SERVER_IPV6} = $ret->{SERVER_IPV6}; $ret->{PROMOTED_DC_NETBIOSNAME} = $ret->{NETBIOSNAME}; $ret->{DC_SERVER} = $dcvars->{DC_SERVER}; $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP}; + $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6}; $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME}; $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME}; $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD}; @@ -1203,10 +1211,12 @@ sub provision_vampire_dc($$$) $ret->{VAMPIRE_DC_SERVER} = $ret->{SERVER}; $ret->{VAMPIRE_DC_SERVER_IP} = $ret->{SERVER_IP}; + $ret->{VAMPIRE_DC_SERVER_IPV6} = $ret->{SERVER_IPV6}; $ret->{VAMPIRE_DC_NETBIOSNAME} = $ret->{NETBIOSNAME}; $ret->{DC_SERVER} = $dcvars->{DC_SERVER}; $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP}; + $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6}; $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME}; $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME}; $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD}; @@ -1268,10 +1278,12 @@ sub provision_subdom_dc($$$) $ret->{SUBDOM_DC_SERVER} = $ret->{SERVER}; $ret->{SUBDOM_DC_SERVER_IP} = $ret->{SERVER_IP}; + $ret->{SUBDOM_DC_SERVER_IPV6} = $ret->{SERVER_IPV6}; $ret->{SUBDOM_DC_NETBIOSNAME} = $ret->{NETBIOSNAME}; $ret->{DC_SERVER} = $dcvars->{DC_SERVER}; $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP}; + $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6}; $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME}; $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME}; $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD}; @@ -1303,6 +1315,7 @@ sub provision_dc($$) $ret->{NETBIOSALIAS} = "localdc1-a"; $ret->{DC_SERVER} = $ret->{SERVER}; $ret->{DC_SERVER_IP} = $ret->{SERVER_IP}; + $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6}; $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME}; $ret->{DC_USERNAME} = $ret->{USERNAME}; $ret->{DC_PASSWORD} = $ret->{PASSWORD}; @@ -1353,6 +1366,7 @@ sub provision_fl2003dc($$) $ret->{DC_SERVER} = $ret->{SERVER}; $ret->{DC_SERVER_IP} = $ret->{SERVER_IP}; + $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6}; $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME}; $ret->{DC_USERNAME} = $ret->{USERNAME}; $ret->{DC_PASSWORD} = $ret->{PASSWORD}; @@ -1475,10 +1489,12 @@ sub provision_rodc($$$) $ret->{RODC_DC_SERVER} = $ret->{SERVER}; $ret->{RODC_DC_SERVER_IP} = $ret->{SERVER_IP}; + $ret->{RODC_DC_SERVER_IPV6} = $ret->{SERVER_IPV6}; $ret->{RODC_DC_NETBIOSNAME} = $ret->{NETBIOSNAME}; $ret->{DC_SERVER} = $dcvars->{DC_SERVER}; $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP}; + $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6}; $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME}; $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME}; $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD}; @@ -1595,6 +1611,7 @@ sub provision_plugin_s4_dc($$) $ret->{DC_SERVER} = $ret->{SERVER}; $ret->{DC_SERVER_IP} = $ret->{SERVER_IP}; + $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6}; $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME}; $ret->{DC_USERNAME} = $ret->{USERNAME}; $ret->{DC_PASSWORD} = $ret->{PASSWORD}; @@ -1637,6 +1654,7 @@ sub provision_chgdcpass($$) $ret->{DC_SERVER} = $ret->{SERVER}; $ret->{DC_SERVER_IP} = $ret->{SERVER_IP}; + $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6}; $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME}; $ret->{DC_USERNAME} = $ret->{USERNAME}; $ret->{DC_PASSWORD} = $ret->{PASSWORD}; -- 1.9.1 From 13207a58643bc923303518c98e02f7a0a74bfd01 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 19 Jun 2014 17:21:16 +0200 Subject: [PATCH 22/29] selftest/Samba3: also bind to ipv6 Signed-off-by: Stefan Metzmacher --- selftest/target/Samba3.pm | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index a17f2f6..8c15d37 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -229,6 +229,7 @@ sub setup_s3dc($$) $vars->{DC_SERVER} = $vars->{SERVER}; $vars->{DC_SERVER_IP} = $vars->{SERVER_IP}; + $vars->{DC_SERVER_IPV6} = $vars->{SERVER_IPV6}; $vars->{DC_NETBIOSNAME} = $vars->{NETBIOSNAME}; $vars->{DC_USERNAME} = $vars->{USERNAME}; $vars->{DC_PASSWORD} = $vars->{PASSWORD}; @@ -273,6 +274,7 @@ sub setup_member($$$) $ret->{DC_SERVER} = $s3dcvars->{SERVER}; $ret->{DC_SERVER_IP} = $s3dcvars->{SERVER_IP}; + $ret->{DC_SERVER_IPV6} = $s3dcvars->{SERVER_IPV6}; $ret->{DC_NETBIOSNAME} = $s3dcvars->{NETBIOSNAME}; $ret->{DC_USERNAME} = $s3dcvars->{USERNAME}; $ret->{DC_PASSWORD} = $s3dcvars->{PASSWORD}; @@ -344,6 +346,7 @@ sub setup_admember($$$$) $ret->{DC_SERVER} = $dcvars->{SERVER}; $ret->{DC_SERVER_IP} = $dcvars->{SERVER_IP}; + $ret->{DC_SERVER_IPV6} = $dcvars->{SERVER_IPV6}; $ret->{DC_NETBIOSNAME} = $dcvars->{NETBIOSNAME}; $ret->{DC_USERNAME} = $dcvars->{USERNAME}; $ret->{DC_PASSWORD} = $dcvars->{PASSWORD}; @@ -423,6 +426,7 @@ sub setup_admember_rfc2307($$$$) $ret->{DC_SERVER} = $dcvars->{SERVER}; $ret->{DC_SERVER_IP} = $dcvars->{SERVER_IP}; + $ret->{DC_SERVER_IPV6} = $dcvars->{SERVER_IPV6}; $ret->{DC_NETBIOSNAME} = $dcvars->{NETBIOSNAME}; $ret->{DC_USERNAME} = $dcvars->{USERNAME}; $ret->{DC_PASSWORD} = $dcvars->{PASSWORD}; @@ -814,6 +818,7 @@ sub provision($$$$$$) my $swiface = Samba::get_interface($server); my %ret = (); my $server_ip = "127.0.0.$swiface"; + my $server_ipv6 = sprintf("fd00:0000:0000:0000:0000:0000:5357:5f%02x", $swiface); my $domain = "SAMBA-TEST"; my $unix_name = ($ENV{USER} or $ENV{LOGNAME} or `PATH=/usr/ucb:$ENV{PATH} whoami`); @@ -918,7 +923,7 @@ sub provision($$$$$$) close(MSDFS_TARGET); chmod 0666, $msdfs_target; symlink "msdfs:$server_ip\\ro-tmp", "$msdfs_shrdir/msdfs-src1"; - symlink "msdfs:$server_ip\\ro-tmp", "$msdfs_shrdir/deeppath/msdfs-src2"; + symlink "msdfs:$server_ipv6\\ro-tmp", "$msdfs_shrdir/deeppath/msdfs-src2"; my $conffile="$libdir/server.conf"; @@ -973,7 +978,7 @@ sub provision($$$$$$) print CONF " [global] netbios name = $server - interfaces = $server_ip/8 + interfaces = $server_ip/8 $server_ipv6/64 bind interfaces only = yes panic action = cd $self->{srcdir} && $self->{srcdir}/selftest/gdb_backtrace %d %\$(MAKE_TEST_BINARY) smbd:suicide mode = yes @@ -1222,8 +1227,8 @@ domadmins:X:$gid_domadmins: warn("Unable to open $nss_wrapper_hosts"); return undef; } - print HOSTS "${server_ip} ${hostname}.samba.example.com ${hostname} -"; + print HOSTS "${server_ip} ${hostname}.samba.example.com ${hostname}\n"; + print HOSTS "${server_ipv6} ${hostname}.samba.example.com ${hostname}\n"; close(HOSTS); @@ -1250,7 +1255,8 @@ domadmins:X:$gid_domadmins: print "DONE\n"; open(DNS_UPDATE_LIST, ">$prefix/dns_update_list") or die("Unable to open $$prefix/dns_update_list"); - print DNS_UPDATE_LIST "A $server. $server_ip"; + print DNS_UPDATE_LIST "A $server. $server_ip\n"; + print DNS_UPDATE_LIST "AAAA $server. $server_ipv6\n"; close(DNS_UPDATE_LIST); if (system("$ENV{SRCDIR_ABS}/source4/scripting/bin/samba_dnsupdate --all-interfaces --use-file=$dns_host_file -s $conffile --update-list=$prefix/dns_update_list --no-substiutions --no-credentials") != 0) { @@ -1258,6 +1264,7 @@ domadmins:X:$gid_domadmins: } $ret{SERVER_IP} = $server_ip; + $ret{SERVER_IPV6} = $server_ipv6; $ret{NMBD_TEST_LOG} = "$prefix/nmbd_test.log"; $ret{NMBD_TEST_LOG_POS} = 0; $ret{WINBINDD_TEST_LOG} = "$prefix/winbindd_test.log"; -- 1.9.1 From 97a0b2e8b55a4f09086060072e5fa5135771cfe6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 19 Aug 2014 10:33:11 +0200 Subject: [PATCH 23/29] python/join: use lowercase for the dnshostname. Signed-off-by: Stefan Metzmacher --- python/samba/join.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/samba/join.py b/python/samba/join.py index f8ede5d..a5211bc 100644 --- a/python/samba/join.py +++ b/python/samba/join.py @@ -134,7 +134,7 @@ class dc_join(object): else: ctx.dns_backend = dns_backend - ctx.dnshostname = "%s.%s" % (ctx.myname, ctx.dnsdomain) + ctx.dnshostname = "%s.%s" % (ctx.myname.lower(), ctx.dnsdomain) ctx.realm = ctx.dnsdomain @@ -1206,7 +1206,7 @@ def join_subdomain(logger=None, server=None, creds=None, lp=None, site=None, ctx.base_dn = samba.dn_from_dns_name(dnsdomain) ctx.domsid = str(security.random_sid()) ctx.acct_dn = None - ctx.dnshostname = "%s.%s" % (ctx.myname, ctx.dnsdomain) + ctx.dnshostname = "%s.%s" % (ctx.myname.lower(), ctx.dnsdomain) ctx.trustdom_pass = samba.generate_random_password(128, 128) ctx.userAccountControl = samba.dsdb.UF_SERVER_TRUST_ACCOUNT | samba.dsdb.UF_TRUSTED_FOR_DELEGATION -- 1.9.1 From 24001d5f2516f7ec32c8e6339f226e9b8283fa7f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Apr 2014 17:26:51 +0200 Subject: [PATCH 24/29] s4:samba_dnsupdate: don't lower case the registered names This matches Windows... Bug: https://bugzilla.samba.org/show_bug.cgi?id=9831 Signed-off-by: Stefan Metzmacher --- source4/scripting/bin/samba_dnsupdate | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source4/scripting/bin/samba_dnsupdate b/source4/scripting/bin/samba_dnsupdate index 68b0f72..0384dd9 100755 --- a/source4/scripting/bin/samba_dnsupdate +++ b/source4/scripting/bin/samba_dnsupdate @@ -136,20 +136,20 @@ class dnsobj(object): self.existing_port = None self.existing_weight = None self.type = list[0] - self.name = list[1].lower() + self.name = list[1] if self.type == 'SRV': if len(list) < 4: raise Exception("Invalid DNS entry %r" % string_form) - self.dest = list[2].lower() + self.dest = list[2] self.port = list[3] elif self.type in ['A', 'AAAA']: self.ip = list[2] # usually $IP, which gets replaced elif self.type == 'CNAME': - self.dest = list[2].lower() + self.dest = list[2] elif self.type == 'NS': - self.dest = list[2].lower() + self.dest = list[2] else: - raise Exception("Received unexpected DNS reply of type %s" % self.type) + raise Exception("Received unexpected DNS reply of type %s: %s" % (self.type, string_form)) def __str__(self): if d.type == "A": -- 1.9.1 From 3713dad0221265b14f3d307a2d505fc42ebde76b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Apr 2014 08:27:26 +0200 Subject: [PATCH 25/29] s4:samba_dnsupdate: fix dnsobj.__str__() We should not implicitly use the global variable 'd'. Bug: https://bugzilla.samba.org/show_bug.cgi?id=9831 Signed-off-by: Stefan Metzmacher --- source4/scripting/bin/samba_dnsupdate | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source4/scripting/bin/samba_dnsupdate b/source4/scripting/bin/samba_dnsupdate index 0384dd9..1b21216 100755 --- a/source4/scripting/bin/samba_dnsupdate +++ b/source4/scripting/bin/samba_dnsupdate @@ -152,15 +152,15 @@ class dnsobj(object): raise Exception("Received unexpected DNS reply of type %s: %s" % (self.type, string_form)) def __str__(self): - if d.type == "A": + if self.type == "A": return "%s %s %s" % (self.type, self.name, self.ip) - if d.type == "AAAA": + if self.type == "AAAA": return "%s %s %s" % (self.type, self.name, self.ip) - if d.type == "SRV": + if self.type == "SRV": return "%s %s %s %s" % (self.type, self.name, self.dest, self.port) - if d.type == "CNAME": + if self.type == "CNAME": return "%s %s %s" % (self.type, self.name, self.dest) - if d.type == "NS": + if self.type == "NS": return "%s %s %s" % (self.type, self.name, self.dest) -- 1.9.1 From c37e18bc3af25834a70cace301c51e0e030a8707 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Apr 2014 08:29:40 +0200 Subject: [PATCH 26/29] s4:samba_dnsupdate: cache the already registered records This way we can delete records which are not used anymore. E.g. if the ip address changed. Bug: https://bugzilla.samba.org/show_bug.cgi?id=9831 Signed-off-by: Stefan Metzmacher --- selftest/target/Samba3.pm | 2 +- source4/dsdb/dns/dns_update.c | 13 ++++ source4/scripting/bin/samba_dnsupdate | 117 +++++++++++++++++++++++++++++----- 3 files changed, 115 insertions(+), 17 deletions(-) diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index 8c15d37..5544105 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -1259,7 +1259,7 @@ domadmins:X:$gid_domadmins: print DNS_UPDATE_LIST "AAAA $server. $server_ipv6\n"; close(DNS_UPDATE_LIST); - if (system("$ENV{SRCDIR_ABS}/source4/scripting/bin/samba_dnsupdate --all-interfaces --use-file=$dns_host_file -s $conffile --update-list=$prefix/dns_update_list --no-substiutions --no-credentials") != 0) { + if (system("$ENV{SRCDIR_ABS}/source4/scripting/bin/samba_dnsupdate --all-interfaces --use-file=$dns_host_file -s $conffile --update-list=$prefix/dns_update_list --update-cache=$prefix/dns_update_cache --no-substiutions --no-credentials") != 0) { die "Unable to update hostname into $dns_host_file"; } diff --git a/source4/dsdb/dns/dns_update.c b/source4/dsdb/dns/dns_update.c index 3e10447..aa617c6 100644 --- a/source4/dsdb/dns/dns_update.c +++ b/source4/dsdb/dns/dns_update.c @@ -397,6 +397,7 @@ struct dnsupdate_RODC_state { struct irpc_message *msg; struct dnsupdate_RODC *r; char *tmp_path; + char *tmp_path2; int fd; }; @@ -406,6 +407,9 @@ static int dnsupdate_RODC_destructor(struct dnsupdate_RODC_state *st) close(st->fd); } unlink(st->tmp_path); + if (st->tmp_path2 != NULL) { + unlink(st->tmp_path2); + } return 0; } @@ -483,6 +487,13 @@ static NTSTATUS dnsupdate_dnsupdate_RODC(struct irpc_message *msg, talloc_set_destructor(st, dnsupdate_RODC_destructor); + st->tmp_path2 = talloc_asprintf(st, "%s.cache", st->tmp_path); + if (!st->tmp_path2) { + talloc_free(st); + r->out.result = NT_STATUS_NO_MEMORY; + return NT_STATUS_OK; + } + sid_dn = ldb_dn_new_fmt(st, s->samdb, "", dom_sid_string(st, r->in.dom_sid)); if (!sid_dn) { talloc_free(st); @@ -575,6 +586,8 @@ static NTSTATUS dnsupdate_dnsupdate_RODC(struct irpc_message *msg, dns_update_command, "--update-list", st->tmp_path, + "--update-cache", + st->tmp_path2, NULL); NT_STATUS_HAVE_NO_MEMORY(req); diff --git a/source4/scripting/bin/samba_dnsupdate b/source4/scripting/bin/samba_dnsupdate index 1b21216..9c7c5e2 100755 --- a/source4/scripting/bin/samba_dnsupdate +++ b/source4/scripting/bin/samba_dnsupdate @@ -63,6 +63,7 @@ parser.add_option("--all-names", action="store_true") parser.add_option("--all-interfaces", action="store_true") parser.add_option("--use-file", type="string", help="Use a file, rather than real DNS calls") parser.add_option("--update-list", type="string", help="Add DNS names from the given file") +parser.add_option("--update-cache", type="string", help="Cache database of already registered records") parser.add_option("--fail-immediately", action='store_true', help="Exit on first failure") parser.add_option("--no-credentials", dest='nocreds', action='store_true', help="don't try and get credentials") parser.add_option("--no-substiutions", dest='nosubs', action='store_true', help="don't try and expands variables in file specified by --update-list") @@ -278,12 +279,14 @@ def get_subst_vars(samdb): return vars -def call_nsupdate(d): +def call_nsupdate(d, op="add"): """call nsupdate for an entry.""" global ccachename, nsupdate_cmd, krb5conf + assert(op in ["add", "delete"]) + if opts.verbose: - print "Calling nsupdate for %s" % d + print "Calling nsupdate for %s (%s)" % (d, op) if opts.use_file is not None: try: @@ -299,8 +302,13 @@ def call_nsupdate(d): wfile = os.fdopen(tmp_fd, 'a') rfile.seek(0) for line in rfile: + if op == "delete": + l = parse_dns_line(line, {}) + if str(l).lower() == str(d).lower(): + continue wfile.write(line) - wfile.write(str(d)+"\n") + if op == "add": + wfile.write(str(d)+"\n") os.rename(tmpfile, opts.use_file) fcntl.lockf(rfile, fcntl.LOCK_UN) return @@ -312,18 +320,18 @@ def call_nsupdate(d): if getattr(d, 'nameservers', None): f.write('server %s\n' % d.nameservers[0]) if d.type == "A": - f.write("update add %s %u A %s\n" % (normalised_name, default_ttl, d.ip)) + f.write("update %s %s %u A %s\n" % (op, normalised_name, default_ttl, d.ip)) if d.type == "AAAA": - f.write("update add %s %u AAAA %s\n" % (normalised_name, default_ttl, d.ip)) + f.write("update %s %s %u AAAA %s\n" % (op, normalised_name, default_ttl, d.ip)) if d.type == "SRV": - if d.existing_port is not None: + if op == "add" and d.existing_port is not None: f.write("update delete %s SRV 0 %s %s %s\n" % (normalised_name, d.existing_weight, d.existing_port, d.dest)) - f.write("update add %s %u SRV 0 100 %s %s\n" % (normalised_name, default_ttl, d.port, d.dest)) + f.write("update %s %s %u SRV 0 100 %s %s\n" % (op, normalised_name, default_ttl, d.port, d.dest)) if d.type == "CNAME": - f.write("update add %s %u CNAME %s\n" % (normalised_name, default_ttl, d.dest)) + f.write("update %s %s %u CNAME %s\n" % (op, normalised_name, default_ttl, d.dest)) if d.type == "NS": - f.write("update add %s %u NS %s\n" % (normalised_name, default_ttl, d.dest)) + f.write("update %s %s %u NS %s\n" % (op, normalised_name, default_ttl, d.dest)) if opts.verbose: f.write("show\n") f.write("send\n") @@ -359,10 +367,12 @@ def call_nsupdate(d): -def rodc_dns_update(d, t): +def rodc_dns_update(d, t, op): '''a single DNS update via the RODC netlogon call''' global sub_vars + assert(op in ["add", "delete"]) + if opts.verbose: print "Calling netlogon RODC update for %s" % d @@ -386,7 +396,10 @@ def rodc_dns_update(d, t): name.weight = 0 if d.port is not None: name.port = int(d.port) - name.dns_register = True + if op == "add": + name.dns_register = True + else: + name.dns_register = False dns_names.names = [ name ] site_name = sub_vars['SITE'].decode('utf-8') @@ -405,10 +418,12 @@ def rodc_dns_update(d, t): sys.exit(1) -def call_rodc_update(d): +def call_rodc_update(d, op="add"): '''RODCs need to use the netlogon API for nsupdate''' global lp, sub_vars + assert(op in ["add", "delete"]) + # we expect failure for 3268 if we aren't a GC if d.port is not None and int(d.port) == 3268: return @@ -428,7 +443,7 @@ def call_rodc_update(d): subname = samba.substitute_var(map[t], sub_vars) if subname.lower() == d.name.lower(): # found a match - do the update - rodc_dns_update(d, t) + rodc_dns_update(d, t, op) return if opts.verbose: print("Unable to map to netlogon DNS update: %s" % d) @@ -440,6 +455,11 @@ if opts.update_list: else: dns_update_list = lp.private_path('dns_update_list') +if opts.update_cache: + dns_update_cache = opts.update_cache +else: + dns_update_cache = lp.private_path('dns_update_cache') + # use our private krb5.conf to avoid problems with the wrong domain # bind9 nsupdate wants the default domain set krb5conf = lp.private_path('krb5.conf') @@ -458,8 +478,31 @@ else: # build up a list of update commands to pass to nsupdate update_list = [] dns_list = [] +cache_list = [] +delete_list = [] dup_set = set() +cache_set = set() + +rebuild_cache = False +try: + cfile = open(dns_update_cache, 'r+') +except IOError: + # Perhaps create it + cfile = open(dns_update_cache, 'w+') + # Open it for reading again, in case someone else got to it first + cfile = open(dns_update_cache, 'r+') +fcntl.lockf(cfile, fcntl.LOCK_EX) +for line in cfile: + line = line.strip() + if line == '' or line[0] == "#": + continue + c = parse_dns_line(line, {}) + if c is None: + continue + if str(c) not in cache_set: + cache_list.append(c) + cache_set.add(str(c)) # read each line, and check that the DNS name exists for line in file: @@ -497,17 +540,50 @@ for d in dns_list: # now check if the entries already exist on the DNS server for d in dns_list: + found = False + for c in cache_list: + if str(c).lower() == str(d).lower(): + found = True + break + if not found: + rebuild_cache = True if opts.all_names or not check_dns_name(d): update_list.append(d) -if len(update_list) == 0: +for c in cache_list: + found = False + for d in dns_list: + if str(c).lower() == str(d).lower(): + found = True + break + if found: + continue + rebuild_cache = True + if not opts.all_names and not check_dns_name(c): + continue + delete_list.append(c) + +if len(delete_list) == 0 and len(update_list) == 0 and not rebuild_cache: if opts.verbose: print "No DNS updates needed" sys.exit(0) # get our krb5 creds -if not opts.nocreds: - get_credentials(lp) +if len(delete_list) != 0 or len(update_list) != 0: + if not opts.nocreds: + get_credentials(lp) + +# ask nsupdate to delete entries as needed +for d in delete_list: + if am_rodc: + if d.name.lower() == domain.lower(): + continue + if not d.type in [ 'A', 'AAAA' ]: + call_rodc_update(d, op="delete") + else: + call_nsupdate(d, op="delete") + else: + call_nsupdate(d, op="delete") # ask nsupdate to add entries as needed for d in update_list: @@ -521,6 +597,15 @@ for d in update_list: else: call_nsupdate(d) +if rebuild_cache: + (file_dir, file_name) = os.path.split(dns_update_cache) + (tmp_fd, tmpfile) = tempfile.mkstemp(dir=file_dir, prefix=file_name, suffix="XXXXXX") + wfile = os.fdopen(tmp_fd, 'a') + for d in dns_list: + wfile.write(str(d)+"\n") + os.rename(tmpfile, dns_update_cache) +fcntl.lockf(cfile, fcntl.LOCK_UN) + # delete the ccache if we created it if ccachename is not None: os.unlink(ccachename) -- 1.9.1 From 5402628265b7f9ec753c2941483fc08e31a1ea13 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 8 Jul 2014 00:05:03 +0200 Subject: [PATCH 27/29] s4:samba_dnsupdate: don't try to be smart when verifying NS records We can't rely on the DNS delegation to be correct in the parent domain. What we really want is to check if we already have registered ourself as a NS record in our own domain. Bug: https://bugzilla.samba.org/show_bug.cgi?id=9831 Signed-off-by: Stefan Metzmacher --- source4/scripting/bin/samba_dnsupdate | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/source4/scripting/bin/samba_dnsupdate b/source4/scripting/bin/samba_dnsupdate index 9c7c5e2..0d001ac 100755 --- a/source4/scripting/bin/samba_dnsupdate +++ b/source4/scripting/bin/samba_dnsupdate @@ -203,25 +203,6 @@ def check_dns_name(d): return False resolver = dns.resolver.Resolver() - if d.type == "NS": - # we need to lookup the nameserver for the parent domain, - # and use that to check the NS record - parent_domain = '.'.join(normalised_name.split('.')[1:]) - try: - ans = resolver.query(parent_domain, 'NS') - except dns.exception.DNSException: - if opts.verbose: - print "Failed to find parent NS for %s" % d - return False - nameservers = set() - for i in range(len(ans)): - try: - ns = resolver.query(str(ans[i]), 'A') - except dns.exception.DNSException: - continue - for j in range(len(ns)): - nameservers.add(str(ns[j])) - d.nameservers = list(nameservers) try: if getattr(d, 'nameservers', None): -- 1.9.1 From c332cefcacc6a9e5f3d7716cc4b765f74fed1e7c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Apr 2014 17:33:50 +0200 Subject: [PATCH 28/29] s4:samba_dnsupdate: provide more substitution variables e.g. IF_RODC This will make the dns_update_list more flexible. Bug: https://bugzilla.samba.org/show_bug.cgi?id=9831 Signed-off-by: Stefan Metzmacher --- source4/scripting/bin/samba_dnsupdate | 57 +++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/source4/scripting/bin/samba_dnsupdate b/source4/scripting/bin/samba_dnsupdate index 0d001ac..30d5608 100755 --- a/source4/scripting/bin/samba_dnsupdate +++ b/source4/scripting/bin/samba_dnsupdate @@ -42,6 +42,7 @@ import samba import optparse from samba import getopt as options from ldb import SCOPE_BASE +from samba import dsdb from samba.auth import system_session from samba.samdb import SamDB from samba.dcerpc import netlogon, winbind @@ -168,10 +169,13 @@ class dnsobj(object): def parse_dns_line(line, sub_vars): """parse a DNS line from.""" if line.startswith("SRV _ldap._tcp.pdc._msdcs.") and not samdb.am_pdc(): + # We keep this as compat to the dns_update_list of 4.0/4.1 if opts.verbose: print "Skipping PDC entry (%s) as we are not a PDC" % line return None subline = samba.substitute_var(line, sub_vars) + if subline == '' or subline[0] == "#": + return None return dnsobj(subline) @@ -255,7 +259,60 @@ def get_subst_vars(samdb): res = samdb.search(base=samdb.get_default_basedn(), scope=SCOPE_BASE, attrs=["objectGUID"]) guid = samdb.schema_format_value("objectGUID", res[0]['objectGUID'][0]) vars['DOMAINGUID'] = guid + + vars['IF_DC'] = "" + vars['IF_RWDC'] = "# " + vars['IF_RODC'] = "# " + vars['IF_PDC'] = "# " + vars['IF_GC'] = "# " + vars['IF_RWGC'] = "# " + vars['IF_ROGC'] = "# " + vars['IF_DNS_DOMAIN'] = "# " + vars['IF_RWDNS_DOMAIN'] = "# " + vars['IF_RODNS_DOMAIN'] = "# " + vars['IF_DNS_FOREST'] = "# " + vars['IF_RWDNS_FOREST'] = "# " + vars['IF_R0DNS_FOREST'] = "# " + am_rodc = samdb.am_rodc() + if am_rodc: + vars['IF_RODC'] = "" + else: + vars['IF_RWDC'] = "" + + if samdb.am_pdc(): + vars['IF_PDC'] = "" + + # check if we "are DNS server" + res = samdb.search(base=samdb.get_config_basedn(), + expression='(objectguid=%s)' % vars['NTDSGUID'], + attrs=["options", "msDS-hasMasterNCs"]) + + if len(res) == 1: + if "options" in res[0]: + options = int(res[0]["options"][0]) + if (options & dsdb.DS_NTDSDSA_OPT_IS_GC) != 0: + vars['IF_GC'] = "" + if am_rodc: + vars['IF_ROGC'] = "" + else: + vars['IF_RWGC'] = "" + + basedn = str(samdb.get_default_basedn()) + if "msDS-hasMasterNCs" in res[0]: + for e in res[0]["msDS-hasMasterNCs"]: + if str(e) == "DC=DomainDnsZones,%s" % basedn: + vars['IF_DNS_DOMAIN'] = "" + if am_rodc: + vars['IF_RODNS_DOMAIN'] = "" + else: + vars['IF_RWDNS_DOMAIN'] = "" + if str(e) == "DC=ForestDnsZones,%s" % basedn: + vars['IF_DNS_FOREST'] = "" + if am_rodc: + vars['IF_RODNS_FOREST'] = "" + else: + vars['IF_RWDNS_FOREST'] = "" return vars -- 1.9.1 From da7b6dacc173e9458bf99d2714b952d58e43f86e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Apr 2014 18:54:13 +0200 Subject: [PATCH 29/29] s4:setup/dns_update_list: make use of the new substitution variables This let us register the same names as Windows Servers. We only exception are the NS records. In future we could add them by using something like this: samba-tool dns add ${HOSTNAME} ${DNSDOMAIN} @ NS ${HOSTNAME} samba-tool dns add ${HOSTNAME} _msdcs.${DNSFOREST} @ NS ${HOSTNAME} samba-tool dns add ${HOSTNAME} ${DNSFOREST} _msdcs NS ${HOSTNAME} Bug: https://bugzilla.samba.org/show_bug.cgi?id=9831 Signed-off-by: Stefan Metzmacher --- source4/setup/dns_update_list | 82 ++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 36 deletions(-) diff --git a/source4/setup/dns_update_list b/source4/setup/dns_update_list index 4da0398..deac459 100644 --- a/source4/setup/dns_update_list +++ b/source4/setup/dns_update_list @@ -1,39 +1,49 @@ # this is a list of DNS entries which will be put into DNS using # dynamic DNS update. It is processed by the samba_dnsupdate script -A ${DNSDOMAIN} $IP -A ${HOSTNAME} $IP -AAAA ${DNSDOMAIN} $IP -AAAA ${HOSTNAME} $IP +A ${HOSTNAME} $IP +AAAA ${HOSTNAME} $IP + +# RW domain controller +${IF_RWDC}A ${DNSDOMAIN} $IP +${IF_RWDC}AAAA ${DNSDOMAIN} $IP +${IF_RWDC}SRV _ldap._tcp.${DNSDOMAIN} ${HOSTNAME} 389 +${IF_RWDC}SRV _ldap._tcp.dc._msdcs.${DNSDOMAIN} ${HOSTNAME} 389 +${IF_RWDC}SRV _ldap._tcp.${DOMAINGUID}.domains._msdcs.${DNSFOREST} ${HOSTNAME} 389 +${IF_RWDC}SRV _kerberos._tcp.${DNSDOMAIN} ${HOSTNAME} 88 +${IF_RWDC}SRV _kerberos._udp.${DNSDOMAIN} ${HOSTNAME} 88 +${IF_RWDC}SRV _kerberos._tcp.dc._msdcs.${DNSDOMAIN} ${HOSTNAME} 88 +${IF_RWDC}SRV _kpasswd._tcp.${DNSDOMAIN} ${HOSTNAME} 464 +${IF_RWDC}SRV _kpasswd._udp.${DNSDOMAIN} ${HOSTNAME} 464 +# RW and RO domain controller +${IF_DC}CNAME ${NTDSGUID}._msdcs.${DNSFOREST} ${HOSTNAME} +${IF_DC}SRV _ldap._tcp.${SITE}._sites.${DNSDOMAIN} ${HOSTNAME} 389 +${IF_DC}SRV _ldap._tcp.${SITE}._sites.dc._msdcs.${DNSDOMAIN} ${HOSTNAME} 389 +${IF_DC}SRV _kerberos._tcp.${SITE}._sites.${DNSDOMAIN} ${HOSTNAME} 88 +${IF_DC}SRV _kerberos._tcp.${SITE}._sites.dc._msdcs.${DNSDOMAIN} ${HOSTNAME} 88 + +# The PDC emulator +${IF_PDC}SRV _ldap._tcp.pdc._msdcs.${DNSDOMAIN} ${HOSTNAME} 389 + +# RW GC servers +${IF_RWGC}A gc._msdcs.${DNSFOREST} $IP +${IF_RWGC}AAAA gc._msdcs.${DNSFOREST} $IP +${IF_RWGC}SRV _gc._tcp.${DNSFOREST} ${HOSTNAME} 3268 +${IF_RWGC}SRV _ldap._tcp.gc._msdcs.${DNSFOREST} ${HOSTNAME} 3268 +# RW and RO GC servers +${IF_GC}SRV _gc._tcp.${SITE}._sites.${DNSFOREST} ${HOSTNAME} 3268 +${IF_GC}SRV _ldap._tcp.${SITE}._sites.gc._msdcs.${DNSFOREST} ${HOSTNAME} 3268 + +# RW DNS servers +${IF_RWDNS_DOMAIN}A DomainDnsZones.${DNSDOMAIN} $IP +${IF_RWDNS_DOMAIN}AAAA DomainDnsZones.${DNSDOMAIN} $IP +${IF_RWDNS_DOMAIN}SRV _ldap._tcp.DomainDnsZones.${DNSDOMAIN} ${HOSTNAME} 389 +# RW and RO DNS servers +${IF_DNS_DOMAIN}SRV _ldap._tcp.${SITE}._sites.DomainDnsZones.${DNSDOMAIN} ${HOSTNAME} 389 + +# RW DNS servers +${IF_RWDNS_FOREST}A ForestDnsZones.${DNSFOREST} $IP +${IF_RWDNS_FOREST}AAAA ForestDnsZones.${DNSFOREST} $IP +${IF_RWDNS_FOREST}SRV _ldap._tcp.ForestDnsZones.${DNSFOREST} ${HOSTNAME} 389 +# RW and RO DNS servers +${IF_DNS_FOREST}SRV _ldap._tcp.${SITE}._sites.ForestDnsZones.${DNSFOREST} ${HOSTNAME} 389 -A gc._msdcs.${DNSFOREST} $IP -AAAA gc._msdcs.${DNSFOREST} $IP - -CNAME ${NTDSGUID}._msdcs.${DNSFOREST} ${HOSTNAME} - -SRV _kpasswd._tcp.${DNSDOMAIN} ${HOSTNAME} 464 -SRV _kpasswd._udp.${DNSDOMAIN} ${HOSTNAME} 464 - -SRV _kerberos._tcp.${DNSDOMAIN} ${HOSTNAME} 88 -SRV _kerberos._tcp.dc._msdcs.${DNSDOMAIN} ${HOSTNAME} 88 -SRV _kerberos._tcp.dc._msdcs.${DNSFOREST} ${HOSTNAME} 88 -SRV _kerberos._tcp.${SITE}._sites.${DNSDOMAIN} ${HOSTNAME} 88 -SRV _kerberos._tcp.${SITE}._sites.dc._msdcs.${DNSDOMAIN} ${HOSTNAME} 88 -SRV _kerberos._tcp.${SITE}._sites.dc._msdcs.${DNSFOREST} ${HOSTNAME} 88 - -SRV _kerberos._udp.${DNSDOMAIN} ${HOSTNAME} 88 - -SRV _ldap._tcp.${DNSDOMAIN} ${HOSTNAME} 389 -SRV _ldap._tcp.dc._msdcs.${DNSDOMAIN} ${HOSTNAME} 389 -SRV _ldap._tcp.dc._msdcs.${DNSFOREST} ${HOSTNAME} 389 -SRV _ldap._tcp.gc._msdcs.${DNSFOREST} ${HOSTNAME} 3268 -SRV _ldap._tcp.pdc._msdcs.${DNSDOMAIN} ${HOSTNAME} 389 -SRV _ldap._tcp.pdc._msdcs.${DNSFOREST} ${HOSTNAME} 389 -SRV _ldap._tcp.${SITE}._sites.${DNSDOMAIN} ${HOSTNAME} 389 -SRV _ldap._tcp.${SITE}._sites.dc._msdcs.${DNSDOMAIN} ${HOSTNAME} 389 -SRV _ldap._tcp.${SITE}._sites.dc._msdcs.${DNSFOREST} ${HOSTNAME} 389 -SRV _ldap._tcp.${SITE}._sites.gc._msdcs.${DNSFOREST} ${HOSTNAME} 3268 -SRV _ldap._tcp.${DOMAINGUID}.domains._msdcs.${DNSFOREST} ${HOSTNAME} 389 - - -SRV _gc._tcp.${DNSFOREST} ${HOSTNAME} 3268 -SRV _gc._tcp.${SITE}._sites.${DNSFOREST} ${HOSTNAME} 3268 -- 1.9.1