The Samba-Bugzilla – Attachment 13706 Details for
Bug 12952
Samba DNS server does not honour wildcards
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for 4.7.1
patch-for-4-7-1.patch (text/plain), 44.74 KB, created by
Garming Sam
on 2017-10-19 00:59:12 UTC
(
hide
)
Description:
Patch for 4.7.1
Filename:
MIME Type:
Creator:
Garming Sam
Created:
2017-10-19 00:59:12 UTC
Size:
44.74 KB
patch
obsolete
>From 1e3de951b1efd96ea18d6671b23b734069337b2b Mon Sep 17 00:00:00 2001 >From: Gary Lockyer <gary@catalyst.net.nz> >Date: Tue, 25 Jul 2017 14:14:53 +1200 >Subject: [PATCH 1/7] dnsserver: Tests for dns wildcard entries > >Add tests for dns wildcards. >Tests validated against Windows Server 2012 R2 > >Signed-off-by: Gary Lockyer <gary@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Garming Sam <garming@catalyst.net.nz> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12952 >(cherry picked from commit 1184770a76800897d59f1c20adaee3b0240697de) >--- > python/samba/tests/dns_wildcard.py | 288 +++++++++++++++++++++++++++++++++++++ > selftest/knownfail.d/dns_wildcard | 2 + > source4/selftest/tests.py | 2 +- > 3 files changed, 291 insertions(+), 1 deletion(-) > create mode 100644 python/samba/tests/dns_wildcard.py > create mode 100644 selftest/knownfail.d/dns_wildcard > >diff --git a/python/samba/tests/dns_wildcard.py b/python/samba/tests/dns_wildcard.py >new file mode 100644 >index 0000000..ca8426a >--- /dev/null >+++ b/python/samba/tests/dns_wildcard.py >@@ -0,0 +1,288 @@ >+# Unix SMB/CIFS implementation. >+# Copyright (C) Andrew Bartlett 2007 >+# >+# 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 <http://www.gnu.org/licenses/>. >+# >+ >+import sys >+from samba import credentials >+from samba.dcerpc import dns, dnsserver >+from samba.netcmd.dns import data_to_dns_record >+from samba.tests.subunitrun import SubunitOptions, TestProgram >+from samba import werror, WERRORError >+from samba.tests.dns_base import DNSTest >+import samba.getopt as options >+import optparse >+ >+parser = optparse.OptionParser( >+ "dns_wildcard.py <server name> <server ip> [options]") >+sambaopts = options.SambaOptions(parser) >+parser.add_option_group(sambaopts) >+ >+# This timeout only has relevance when testing against Windows >+# Format errors tend to return patchy responses, so a timeout is needed. >+parser.add_option("--timeout", type="int", dest="timeout", >+ help="Specify timeout for DNS requests") >+ >+# To run against Windows >+# python python/samba/tests/dns_wildcard.py computer_name ip >+# -U"Administrator%admin_password" >+# --realm=Domain_name >+# --timeout 10 >+# >+ >+# use command line creds if available >+credopts = options.CredentialsOptions(parser) >+parser.add_option_group(credopts) >+subunitopts = SubunitOptions(parser) >+parser.add_option_group(subunitopts) >+ >+opts, args = parser.parse_args() >+ >+lp = sambaopts.get_loadparm() >+creds = credopts.get_credentials(lp) >+ >+timeout = opts.timeout >+ >+if len(args) < 2: >+ parser.print_usage() >+ sys.exit(1) >+ >+server_name = args[0] >+server_ip = args[1] >+creds.set_krb_forwardable(credentials.NO_KRB_FORWARDABLE) >+ >+WILDCARD_IP = "1.1.1.1" >+WILDCARD = "*.wildcardtest" >+EXACT_IP = "1.1.1.2" >+EXACT = "exact.wildcardtest" >+LEVEL2_WILDCARD_IP = "1.1.1.3" >+LEVEL2_WILDCARD = "*.level2.wildcardtest" >+LEVEL2_EXACT_IP = "1.1.1.4" >+LEVEL2_EXACT = "exact.level2.wildcardtest" >+ >+ >+class TestWildCardQueries(DNSTest): >+ >+ def setUp(self): >+ super(TestWildCardQueries, self).setUp() >+ global server, server_ip, lp, creds, timeout >+ self.server = server_name >+ self.server_ip = server_ip >+ self.lp = lp >+ self.creds = creds >+ self.timeout = timeout >+ >+ # Create the dns records >+ self.dns_records = [(dns.DNS_QTYPE_A, >+ "%s.%s" % (WILDCARD, self.get_dns_domain()), >+ WILDCARD_IP), >+ (dns.DNS_QTYPE_A, >+ "%s.%s" % (EXACT, self.get_dns_domain()), >+ EXACT_IP), >+ (dns.DNS_QTYPE_A, >+ ("%s.%s" % ( >+ LEVEL2_WILDCARD, >+ self.get_dns_domain())), >+ LEVEL2_WILDCARD_IP), >+ (dns.DNS_QTYPE_A, >+ ("%s.%s" % ( >+ LEVEL2_EXACT, >+ self.get_dns_domain())), >+ LEVEL2_EXACT_IP)] >+ >+ c = self.dns_connect() >+ for (typ, name, data) in self.dns_records: >+ self.add_record(c, typ, name, data) >+ >+ def tearDown(self): >+ c = self.dns_connect() >+ for (typ, name, data) in self.dns_records: >+ self.delete_record(c, typ, name, data) >+ >+ def dns_connect(self): >+ binding_str = "ncacn_ip_tcp:%s[sign]" % self.server_ip >+ return dnsserver.dnsserver(binding_str, self.lp, self.creds) >+ >+ def delete_record(self, dns_conn, typ, name, data): >+ >+ rec = data_to_dns_record(typ, data) >+ del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF() >+ del_rec_buf.rec = rec >+ >+ try: >+ dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN, >+ 0, >+ self.server, >+ self.get_dns_domain(), >+ name, >+ None, >+ del_rec_buf) >+ except WERRORError as e: >+ # Ignore record does not exist errors >+ if e.args[0] != werror.WERR_DNS_ERROR_NAME_DOES_NOT_EXIST: >+ raise e >+ >+ def add_record(self, dns_conn, typ, name, data): >+ >+ rec = data_to_dns_record(typ, data) >+ add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF() >+ add_rec_buf.rec = rec >+ try: >+ dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN, >+ 0, >+ self.server, >+ self.get_dns_domain(), >+ name, >+ add_rec_buf, >+ None) >+ except WERRORError as e: >+ raise e >+ >+ def test_one_a_query_match_wildcard(self): >+ "Query an A record, should match the wildcard entry" >+ >+ p = self.make_name_packet(dns.DNS_OPCODE_QUERY) >+ questions = [] >+ >+ # Check the record >+ name = "miss.wildcardtest.%s" % self.get_dns_domain() >+ q = self.make_name_question(name, >+ dns.DNS_QTYPE_A, >+ dns.DNS_QCLASS_IN) >+ questions.append(q) >+ >+ self.finish_name_packet(p, questions) >+ (response, response_packet) =\ >+ self.dns_transaction_udp(p, host=self.server_ip) >+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) >+ self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) >+ self.assertEquals(response.ancount, 1) >+ self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_A) >+ self.assertEquals(response.answers[0].rdata, WILDCARD_IP) >+ >+ def test_one_a_query_wildcard_entry(self): >+ "Query the wildcard entry" >+ >+ p = self.make_name_packet(dns.DNS_OPCODE_QUERY) >+ questions = [] >+ >+ # Check the record >+ name = "%s.%s" % (WILDCARD, self.get_dns_domain()) >+ q = self.make_name_question(name, >+ dns.DNS_QTYPE_A, >+ dns.DNS_QCLASS_IN) >+ questions.append(q) >+ >+ self.finish_name_packet(p, questions) >+ (response, response_packet) =\ >+ self.dns_transaction_udp(p, host=self.server_ip) >+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) >+ self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) >+ self.assertEquals(response.ancount, 1) >+ self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_A) >+ self.assertEquals(response.answers[0].rdata, WILDCARD_IP) >+ >+ def test_one_a_query_exact_match(self): >+ """Query an entry that matches the wild card but has an exact match as >+ well. >+ """ >+ p = self.make_name_packet(dns.DNS_OPCODE_QUERY) >+ questions = [] >+ >+ # Check the record >+ name = "%s.%s" % (EXACT, self.get_dns_domain()) >+ q = self.make_name_question(name, >+ dns.DNS_QTYPE_A, >+ dns.DNS_QCLASS_IN) >+ questions.append(q) >+ >+ self.finish_name_packet(p, questions) >+ (response, response_packet) =\ >+ self.dns_transaction_udp(p, host=self.server_ip) >+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) >+ self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) >+ self.assertEquals(response.ancount, 1) >+ self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_A) >+ self.assertEquals(response.answers[0].rdata, EXACT_IP) >+ >+ def test_one_a_query_match_wildcard_l2(self): >+ "Query an A record, should match the level 2 wildcard entry" >+ >+ p = self.make_name_packet(dns.DNS_OPCODE_QUERY) >+ questions = [] >+ >+ # Check the record >+ name = "miss.level2.wildcardtest.%s" % self.get_dns_domain() >+ q = self.make_name_question(name, >+ dns.DNS_QTYPE_A, >+ dns.DNS_QCLASS_IN) >+ questions.append(q) >+ >+ self.finish_name_packet(p, questions) >+ (response, response_packet) =\ >+ self.dns_transaction_udp(p, host=self.server_ip) >+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) >+ self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) >+ self.assertEquals(response.ancount, 1) >+ self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_A) >+ self.assertEquals(response.answers[0].rdata, LEVEL2_WILDCARD_IP) >+ >+ def test_one_a_query_exact_match_l2(self): >+ """Query an entry that matches the wild card but has an exact match as >+ well. >+ """ >+ p = self.make_name_packet(dns.DNS_OPCODE_QUERY) >+ questions = [] >+ >+ # Check the record >+ name = "%s.%s" % (LEVEL2_EXACT, self.get_dns_domain()) >+ q = self.make_name_question(name, >+ dns.DNS_QTYPE_A, >+ dns.DNS_QCLASS_IN) >+ questions.append(q) >+ >+ self.finish_name_packet(p, questions) >+ (response, response_packet) =\ >+ self.dns_transaction_udp(p, host=self.server_ip) >+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) >+ self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) >+ self.assertEquals(response.ancount, 1) >+ self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_A) >+ self.assertEquals(response.answers[0].rdata, LEVEL2_EXACT_IP) >+ >+ def test_one_a_query_wildcard_entry_l2(self): >+ "Query the level 2 wildcard entry" >+ >+ p = self.make_name_packet(dns.DNS_OPCODE_QUERY) >+ questions = [] >+ >+ # Check the record >+ name = "%s.%s" % (LEVEL2_WILDCARD, self.get_dns_domain()) >+ q = self.make_name_question(name, >+ dns.DNS_QTYPE_A, >+ dns.DNS_QCLASS_IN) >+ questions.append(q) >+ >+ self.finish_name_packet(p, questions) >+ (response, response_packet) =\ >+ self.dns_transaction_udp(p, host=self.server_ip) >+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) >+ self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) >+ self.assertEquals(response.ancount, 1) >+ self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_A) >+ self.assertEquals(response.answers[0].rdata, LEVEL2_WILDCARD_IP) >+ >+ >+TestProgram(module=__name__, opts=subunitopts) >diff --git a/selftest/knownfail.d/dns_wildcard b/selftest/knownfail.d/dns_wildcard >new file mode 100644 >index 0000000..7e7892f >--- /dev/null >+++ b/selftest/knownfail.d/dns_wildcard >@@ -0,0 +1,2 @@ >+^samba.tests.dns_wildcard.__main__.TestWildCardQueries.test_one_a_query_match_wildcard\(ad_dc\) >+^samba.tests.dns_wildcard.__main__.TestWildCardQueries.test_one_a_query_match_wildcard_l2\(ad_dc\) >diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py >index 4bcbdc6..012f87a 100755 >--- a/source4/selftest/tests.py >+++ b/source4/selftest/tests.py >@@ -367,7 +367,7 @@ plantestsuite_loadlist("samba.tests.dns", "vampire_dc:local", [python, os.path.j > plantestsuite_loadlist("samba.tests.dns_forwarder", "fl2003dc:local", [python, os.path.join(srcdir(), "python/samba/tests/dns_forwarder.py"), '$SERVER', '$SERVER_IP', '$DNS_FORWARDER1', '$DNS_FORWARDER2', '--machine-pass', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) > > plantestsuite_loadlist("samba.tests.dns_tkey", "fl2008r2dc", [python, os.path.join(srcdir(), "python/samba/tests/dns_tkey.py"), '$SERVER', '$SERVER_IP', '--machine-pass', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) >- >+plantestsuite_loadlist("samba.tests.dns_wildcard", "ad_dc", [python, os.path.join(srcdir(), "python/samba/tests/dns_wildcard.py"), '$SERVER', '$SERVER_IP', '--machine-pass', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) > for t in smbtorture4_testsuites("dns_internal."): > plansmbtorture4testsuite(t, "ad_dc_ntvfs:local", '//$SERVER/whavever') > >-- >1.9.1 > > >From a3caf90b255d789c59c1630d52fbe6b122797e24 Mon Sep 17 00:00:00 2001 >From: Gary Lockyer <gary@catalyst.net.nz> >Date: Thu, 3 Aug 2017 15:12:51 +1200 >Subject: [PATCH 2/7] dnsserver: Tighten DNS name checking > >Add checks for the maximum permitted length, maximum number of labels >and the maximum label length. These extra checks will be used by the >DNS wild card handling. > >Signed-off-by: Gary Lockyer <gary@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Garming Sam <garming@catalyst.net.nz> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12952 >(cherry picked from commit 34acf5a99214639e5e7792a9e85d24c9fd7640ac) >--- > librpc/idl/dns.idl | 3 +++ > source4/dns_server/dnsserver_common.c | 35 +++++++++++++++++++++++++++++------ > 2 files changed, 32 insertions(+), 6 deletions(-) > >diff --git a/librpc/idl/dns.idl b/librpc/idl/dns.idl >index aebb106..8e8eed5 100644 >--- a/librpc/idl/dns.idl >+++ b/librpc/idl/dns.idl >@@ -18,6 +18,9 @@ import "misc.idl", "dnsp.idl"; > interface dns > { > const int DNS_SERVICE_PORT = 53; >+ const int DNS_MAX_LABELS = 127; >+ const int DNS_MAX_DOMAIN_LENGTH = 253; >+ const int DNS_MAX_LABEL_LENGTH = 63; > > typedef [public,bitmap16bit] bitmap { > DNS_RCODE = 0x000F, >diff --git a/source4/dns_server/dnsserver_common.c b/source4/dns_server/dnsserver_common.c >index a56ff08..2a81b83 100644 >--- a/source4/dns_server/dnsserver_common.c >+++ b/source4/dns_server/dnsserver_common.c >@@ -246,25 +246,48 @@ static int rec_cmp(const struct dnsp_DnssrvRpcRecord *r1, > } > > /* >- * Check for valid DNS names. These are names which are non-empty, do not >- * start with a dot and do not have any empty segments. >+ * Check for valid DNS names. These are names which: >+ * - are non-empty >+ * - do not start with a dot >+ * - do not have any empty labels >+ * - have no more than 127 labels >+ * - are no longer than 253 characters >+ * - none of the labels exceed 63 characters > */ > WERROR dns_name_check(TALLOC_CTX *mem_ctx, size_t len, const char *name) > { > size_t i; >+ unsigned int labels = 0; >+ unsigned int label_len = 0; > > if (len == 0) { > return WERR_DS_INVALID_DN_SYNTAX; > } > >+ if (len > 1 && name[0] == '.') { >+ return WERR_DS_INVALID_DN_SYNTAX; >+ } >+ >+ if ((len - 1) > DNS_MAX_DOMAIN_LENGTH) { >+ return WERR_DS_INVALID_DN_SYNTAX; >+ } >+ > for (i = 0; i < len - 1; i++) { > if (name[i] == '.' && name[i+1] == '.') { > return WERR_DS_INVALID_DN_SYNTAX; > } >- } >- >- if (len > 1 && name[0] == '.') { >- return WERR_DS_INVALID_DN_SYNTAX; >+ if (name[i] == '.') { >+ labels++; >+ if (labels > DNS_MAX_LABELS) { >+ return WERR_DS_INVALID_DN_SYNTAX; >+ } >+ label_len = 0; >+ } else { >+ label_len++; >+ if (label_len > DNS_MAX_LABEL_LENGTH) { >+ return WERR_DS_INVALID_DN_SYNTAX; >+ } >+ } > } > > return WERR_OK; >-- >1.9.1 > > >From eae4c479d1dfcc7ed10001c133941c657787032b Mon Sep 17 00:00:00 2001 >From: Gary Lockyer <gary@catalyst.net.nz> >Date: Thu, 3 Aug 2017 15:12:02 +1200 >Subject: [PATCH 3/7] dnsserver: Add support for dns wildcards > >Add support for dns wildcard records. i.e. if the following records >exist > > exact.samba.example.com 3600 A 1.1.1.1 > *.samba.example.com 3600 A 1.1.1.2 > >look up on exact.samba.example.com will return 1.1.1.1 >look up on *.samba.example.com will return 1.1.1.2 >look up on other.samba.example.com will return 1.1.1.2 > >Signed-off-by: Gary Lockyer <gary@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Garming Sam <garming@catalyst.net.nz> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12952 >(cherry picked from commit edcbc991253f4d6f59ef9a43a691c66cbbdc2b6d) >--- > selftest/knownfail.d/dns_wildcard | 2 - > source4/dns_server/dlz_bind9.c | 4 +- > source4/dns_server/dns_query.c | 5 +- > source4/dns_server/dns_server.h | 5 + > source4/dns_server/dns_utils.c | 18 ++ > source4/dns_server/dnsserver_common.c | 348 ++++++++++++++++++++++++++++++++++ > source4/dns_server/dnsserver_common.h | 5 + > 7 files changed, 380 insertions(+), 7 deletions(-) > delete mode 100644 selftest/knownfail.d/dns_wildcard > >diff --git a/selftest/knownfail.d/dns_wildcard b/selftest/knownfail.d/dns_wildcard >deleted file mode 100644 >index 7e7892f..0000000 >--- a/selftest/knownfail.d/dns_wildcard >+++ /dev/null >@@ -1,2 +0,0 @@ >-^samba.tests.dns_wildcard.__main__.TestWildCardQueries.test_one_a_query_match_wildcard\(ad_dc\) >-^samba.tests.dns_wildcard.__main__.TestWildCardQueries.test_one_a_query_match_wildcard_l2\(ad_dc\) >diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c >index 7096f47..6ef378c 100644 >--- a/source4/dns_server/dlz_bind9.c >+++ b/source4/dns_server/dlz_bind9.c >@@ -865,8 +865,8 @@ static isc_result_t dlz_lookup_types(struct dlz_bind9_data *state, > return ISC_R_NOMEMORY; > } > >- werr = dns_common_lookup(state->samdb, tmp_ctx, dn, >- &records, &num_records, NULL); >+ werr = dns_common_wildcard_lookup(state->samdb, tmp_ctx, dn, >+ &records, &num_records); > if (W_ERROR_IS_OK(werr)) { > break; > } >diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c >index b8ecc2e..e8de304 100644 >--- a/source4/dns_server/dns_query.c >+++ b/source4/dns_server/dns_query.c >@@ -625,9 +625,8 @@ static struct tevent_req *handle_authoritative_send( > if (tevent_req_werror(req, werr)) { > return tevent_req_post(req, ev); > } >- >- werr = dns_lookup_records(dns, state, dn, &state->recs, >- &state->rec_count); >+ werr = dns_lookup_records_wildcard(dns, state, dn, &state->recs, >+ &state->rec_count); > TALLOC_FREE(dn); > if (tevent_req_werror(req, werr)) { > return tevent_req_post(req, ev); >diff --git a/source4/dns_server/dns_server.h b/source4/dns_server/dns_server.h >index 5395ff9..382b6bd 100644 >--- a/source4/dns_server/dns_server.h >+++ b/source4/dns_server/dns_server.h >@@ -95,6 +95,11 @@ WERROR dns_lookup_records(struct dns_server *dns, > struct ldb_dn *dn, > struct dnsp_DnssrvRpcRecord **records, > uint16_t *rec_count); >+WERROR dns_lookup_records_wildcard(struct dns_server *dns, >+ TALLOC_CTX *mem_ctx, >+ struct ldb_dn *dn, >+ struct dnsp_DnssrvRpcRecord **records, >+ uint16_t *rec_count); > WERROR dns_replace_records(struct dns_server *dns, > TALLOC_CTX *mem_ctx, > struct ldb_dn *dn, >diff --git a/source4/dns_server/dns_utils.c b/source4/dns_server/dns_utils.c >index c728eaa..ee35bd2 100644 >--- a/source4/dns_server/dns_utils.c >+++ b/source4/dns_server/dns_utils.c >@@ -107,6 +107,10 @@ bool dns_records_match(struct dnsp_DnssrvRpcRecord *rec1, > return false; > } > >+/* >+ * Lookup a DNS record, performing an exact match. >+ * i.e. DNS wild card records are not considered. >+ */ > WERROR dns_lookup_records(struct dns_server *dns, > TALLOC_CTX *mem_ctx, > struct ldb_dn *dn, >@@ -117,6 +121,20 @@ WERROR dns_lookup_records(struct dns_server *dns, > records, rec_count, NULL); > } > >+/* >+ * Lookup a DNS record, will match DNS wild card records if an exact match >+ * is not found. >+ */ >+WERROR dns_lookup_records_wildcard(struct dns_server *dns, >+ TALLOC_CTX *mem_ctx, >+ struct ldb_dn *dn, >+ struct dnsp_DnssrvRpcRecord **records, >+ uint16_t *rec_count) >+{ >+ return dns_common_wildcard_lookup(dns->samdb, mem_ctx, dn, >+ records, rec_count); >+} >+ > WERROR dns_replace_records(struct dns_server *dns, > TALLOC_CTX *mem_ctx, > struct ldb_dn *dn, >diff --git a/source4/dns_server/dnsserver_common.c b/source4/dns_server/dnsserver_common.c >index 2a81b83..217e65b 100644 >--- a/source4/dns_server/dnsserver_common.c >+++ b/source4/dns_server/dnsserver_common.c >@@ -133,6 +133,10 @@ WERROR dns_common_extract(struct ldb_context *samdb, > return WERR_OK; > } > >+/* >+ * Lookup a DNS record, performing an exact match. >+ * i.e. DNS wild card records are not considered. >+ */ > WERROR dns_common_lookup(struct ldb_context *samdb, > TALLOC_CTX *mem_ctx, > struct ldb_dn *dn, >@@ -229,6 +233,350 @@ WERROR dns_common_lookup(struct ldb_context *samdb, > return WERR_OK; > } > >+/* >+ * Build an ldb_parse_tree node for an equality check >+ * >+ * Note: name is assumed to have been validated by dns_name_check >+ * so will be zero terminated and of a reasonable size. >+ */ >+static struct ldb_parse_tree *build_equality_operation( >+ TALLOC_CTX *mem_ctx, >+ bool add_asterix, /* prepend an '*' to the name */ >+ const uint8_t *name, /* the value being matched */ >+ const char *attr, /* the attribute to check name against */ >+ size_t size) /* length of name */ >+{ >+ >+ struct ldb_parse_tree *el = NULL; /* Equality node being built */ >+ struct ldb_val *value = NULL; /* Value the attr will be compared >+ with */ >+ size_t length = 0; /* calculated length of the value >+ including option '*' prefix and >+ '\0' string terminator */ >+ >+ el = talloc(mem_ctx, struct ldb_parse_tree); >+ if (el == NULL) { >+ DBG_ERR("Unable to allocate ldb_parse_tree\n"); >+ return NULL; >+ } >+ >+ el->operation = LDB_OP_EQUALITY; >+ el->u.equality.attr = talloc_strdup(mem_ctx, attr); >+ value = &el->u.equality.value; >+ length = (add_asterix) ? size + 2 : size + 1; >+ value->data = talloc_zero_array(el, uint8_t, length); >+ if (el == NULL) { >+ DBG_ERR("Unable to allocate value->data\n"); >+ TALLOC_FREE(el); >+ return NULL; >+ } >+ >+ value->length = length; >+ if (add_asterix) { >+ value->data[0] = '*'; >+ memcpy(&value->data[1], name, size); >+ } else { >+ memcpy(value->data, name, size); >+ } >+ return el; >+} >+ >+/* >+ * Determine the number of levels in name >+ * essentially the number of '.'s in the name + 1 >+ * >+ * name is assumed to have been validated by dns_name_check >+ */ >+static unsigned int number_of_labels(const struct ldb_val *name) { >+ int x = 0; >+ unsigned int labels = 1; >+ for (x = 0; x < name->length; x++) { >+ if (name->data[x] == '.') { >+ labels++; >+ } >+ } >+ return labels; >+} >+/* >+ * Build a query that matches the target name, and any possible >+ * DNS wild card entries >+ * >+ * Builds a parse tree equivalent to the example query. >+ * >+ * x.y.z -> (|(name=x.y.z)(name=\2a.y.z)(name=\2a.z)(name=\2a)) >+ * >+ * Returns NULL if unable to build the query. >+ * >+ * The first component of the DN is assumed to be the name being looked up >+ * and also that it has been validated by dns_name_check >+ * >+ */ >+#define BASE "(&(objectClass=dnsNode)(!(dNSTombstoned=TRUE))(|(a=b)(c=d)))" >+static struct ldb_parse_tree *build_wildcard_query( >+ TALLOC_CTX *mem_ctx, >+ struct ldb_dn *dn) >+{ >+ const struct ldb_val *name = NULL; /* The DNS name being >+ queried */ >+ const char *attr = NULL; /* The attribute name */ >+ struct ldb_parse_tree *query = NULL; /* The constructed query >+ parse tree*/ >+ struct ldb_parse_tree *wildcard_query = NULL; /* The parse tree for the >+ name and wild card >+ entries */ >+ int labels = 0; /* The number of labels in the name */ >+ >+ attr = ldb_dn_get_rdn_name(dn); >+ if (attr == NULL) { >+ DBG_ERR("Unable to get rdn_name\n"); >+ return NULL; >+ } >+ >+ name = ldb_dn_get_rdn_val(dn); >+ if (name == NULL) { >+ DBG_ERR("Unable to get domain name value\n"); >+ return NULL; >+ } >+ labels = number_of_labels(name); >+ >+ query = ldb_parse_tree(mem_ctx, BASE); >+ if (query == NULL) { >+ DBG_ERR("Unable to parse query %s\n", BASE); >+ return NULL; >+ } >+ >+ /* >+ * The 3rd element of BASE is a place holder which is replaced with >+ * the actual wild card query >+ */ >+ wildcard_query = query->u.list.elements[2]; >+ TALLOC_FREE(wildcard_query->u.list.elements); >+ >+ wildcard_query->u.list.num_elements = labels + 1; >+ wildcard_query->u.list.elements = talloc_array( >+ wildcard_query, >+ struct ldb_parse_tree *, >+ labels + 1); >+ /* >+ * Build the wild card query >+ */ >+ { >+ int x = 0; /* current character in the name */ >+ int l = 0; /* current equality operator index in elements */ >+ struct ldb_parse_tree *el = NULL; /* Equality operator being >+ built */ >+ bool add_asterix = true; /* prepend an '*' to the value */ >+ for (l = 0, x = 0; l < labels && x < name->length; l++) { >+ unsigned int size = name->length - x; >+ add_asterix = (name->data[x] == '.'); >+ el = build_equality_operation( >+ mem_ctx, >+ add_asterix, >+ &name->data[x], >+ attr, >+ size); >+ if (el == NULL) { >+ return NULL; /* Reason will have been logged */ >+ } >+ wildcard_query->u.list.elements[l] = el; >+ >+ /* skip to the start of the next label */ >+ for (;x < name->length && name->data[x] != '.'; x++); >+ } >+ >+ /* Add the base level "*" only query */ >+ el = build_equality_operation(mem_ctx, true, NULL, attr, 0); >+ if (el == NULL) { >+ TALLOC_FREE(query); >+ return NULL; /* Reason will have been logged */ >+ } >+ wildcard_query->u.list.elements[l] = el; >+ } >+ return query; >+} >+ >+/* >+ * Scan the list of records matching a dns wildcard query and return the >+ * best match. >+ * >+ * The best match is either an exact name match, or the longest wild card >+ * entry returned >+ * >+ * i.e. name = a.b.c candidates *.b.c, *.c, - *.b.c would be selected >+ * name = a.b.c candidates a.b.c, *.b.c, *.c - a.b.c would be selected >+ */ >+static struct ldb_message *get_best_match(struct ldb_dn *dn, >+ struct ldb_result *result) >+{ >+ int matched = 0; /* Index of the current best match in result */ >+ size_t length = 0; /* The length of the current candidate */ >+ const struct ldb_val *target = NULL; /* value we're looking for */ >+ const struct ldb_val *candidate = NULL; /* current candidate value */ >+ int x = 0; >+ >+ target = ldb_dn_get_rdn_val(dn); >+ for(x = 0; x < result->count; x++) { >+ candidate = ldb_dn_get_rdn_val(result->msgs[x]->dn); >+ if (strncasecmp((char *) target->data, >+ (char *) candidate->data, >+ target->length) == 0) { >+ /* Exact match stop searching and return */ >+ return result->msgs[x]; >+ } >+ if (candidate->length > length) { >+ matched = x; >+ length = candidate->length; >+ } >+ } >+ return result->msgs[matched]; >+} >+ >+/* >+ * Look up a DNS entry, if an exact match does not exist, return the >+ * closest matching DNS wildcard entry if available >+ * >+ * Returns: LDB_ERR_NO_SUCH_OBJECT If no matching record exists >+ * LDB_ERR_OPERATIONS_ERROR If the query fails >+ * LDB_SUCCESS If a matching record was retrieved >+ * >+ */ >+static int dns_wildcard_lookup(struct ldb_context *samdb, >+ TALLOC_CTX *mem_ctx, >+ struct ldb_dn *dn, >+ struct ldb_message **msg) >+{ >+ static const char * const attrs[] = { >+ "dnsRecord", >+ "dNSTombstoned", >+ NULL >+ }; >+ struct ldb_dn *parent = NULL; /* The parent dn */ >+ struct ldb_result *result = NULL; /* Results of the search */ >+ int ret; /* Return code */ >+ struct ldb_parse_tree *query = NULL; /* The query to run */ >+ struct ldb_request *request = NULL; /* LDB request for the query op */ >+ struct ldb_message *match = NULL; /* the best matching DNS record */ >+ TALLOC_CTX *frame = talloc_stackframe(); >+ >+ parent = ldb_dn_get_parent(frame, dn); >+ if (parent == NULL) { >+ DBG_ERR("Unable to extract parent from dn\n"); >+ TALLOC_FREE(frame); >+ return LDB_ERR_OPERATIONS_ERROR; >+ } >+ >+ query = build_wildcard_query(frame, dn); >+ if (query == NULL) { >+ TALLOC_FREE(frame); >+ return LDB_ERR_OPERATIONS_ERROR; >+ } >+ >+ result = talloc_zero(mem_ctx, struct ldb_result); >+ if (result == NULL) { >+ TALLOC_FREE(frame); >+ DBG_ERR("Unable to allocate ldb_result\n"); >+ return LDB_ERR_OPERATIONS_ERROR; >+ } >+ >+ ret = ldb_build_search_req_ex(&request, >+ samdb, >+ frame, >+ parent, >+ LDB_SCOPE_ONELEVEL, >+ query, >+ attrs, >+ NULL, >+ result, >+ ldb_search_default_callback, >+ NULL); >+ if (ret != LDB_SUCCESS) { >+ TALLOC_FREE(frame); >+ DBG_ERR("ldb_build_search_req_ex returned %d\n", ret); >+ return ret; >+ } >+ >+ ret = ldb_request(samdb, request); >+ if (ret != LDB_SUCCESS) { >+ TALLOC_FREE(frame); >+ return ret; >+ } >+ >+ ret = ldb_wait(request->handle, LDB_WAIT_ALL); >+ if (ret != LDB_SUCCESS) { >+ TALLOC_FREE(frame); >+ return ret; >+ } >+ >+ if (result->count == 0) { >+ TALLOC_FREE(frame); >+ return LDB_ERR_NO_SUCH_OBJECT; >+ } >+ >+ match = get_best_match(dn, result); >+ if (match == NULL) { >+ TALLOC_FREE(frame); >+ return LDB_ERR_OPERATIONS_ERROR; >+ } >+ >+ *msg = talloc_move(mem_ctx, &match); >+ TALLOC_FREE(frame); >+ return LDB_SUCCESS; >+} >+ >+/* >+ * Lookup a DNS record, will match DNS wild card records if an exact match >+ * is not found. >+ */ >+WERROR dns_common_wildcard_lookup(struct ldb_context *samdb, >+ TALLOC_CTX *mem_ctx, >+ struct ldb_dn *dn, >+ struct dnsp_DnssrvRpcRecord **records, >+ uint16_t *num_records) >+{ >+ int ret; >+ WERROR werr; >+ struct ldb_message *msg = NULL; >+ struct ldb_message_element *el = NULL; >+ const struct ldb_val *name = NULL; >+ >+ *records = NULL; >+ *num_records = 0; >+ >+ name = ldb_dn_get_rdn_val(dn); >+ if (name == NULL) { >+ return DNS_ERR(NAME_ERROR); >+ } >+ >+ werr = dns_name_check( >+ mem_ctx, >+ strlen((const char*)name->data), >+ (const char*) name->data); >+ if (!W_ERROR_IS_OK(werr)) { >+ return werr; >+ } >+ >+ ret = dns_wildcard_lookup(samdb, mem_ctx, dn, &msg); >+ if (ret == LDB_ERR_OPERATIONS_ERROR) { >+ return DNS_ERR(SERVER_FAILURE); >+ } >+ if (ret != LDB_SUCCESS) { >+ return DNS_ERR(NAME_ERROR); >+ } >+ >+ el = ldb_msg_find_element(msg, "dnsRecord"); >+ if (el == NULL) { >+ return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST; >+ } >+ >+ werr = dns_common_extract(samdb, el, mem_ctx, records, num_records); >+ TALLOC_FREE(msg); >+ if (!W_ERROR_IS_OK(werr)) { >+ return werr; >+ } >+ >+ return WERR_OK; >+} >+ > static int rec_cmp(const struct dnsp_DnssrvRpcRecord *r1, > const struct dnsp_DnssrvRpcRecord *r2) > { >diff --git a/source4/dns_server/dnsserver_common.h b/source4/dns_server/dnsserver_common.h >index b615e2d..f2be44f 100644 >--- a/source4/dns_server/dnsserver_common.h >+++ b/source4/dns_server/dnsserver_common.h >@@ -47,6 +47,11 @@ WERROR dns_common_lookup(struct ldb_context *samdb, > struct dnsp_DnssrvRpcRecord **records, > uint16_t *num_records, > bool *tombstoned); >+WERROR dns_common_wildcard_lookup(struct ldb_context *samdb, >+ TALLOC_CTX *mem_ctx, >+ struct ldb_dn *dn, >+ struct dnsp_DnssrvRpcRecord **records, >+ uint16_t *num_records); > WERROR dns_name_check(TALLOC_CTX *mem_ctx, > size_t len, > const char *name); >-- >1.9.1 > > >From 30f57db8d321eb89740454782009b985175a4e70 Mon Sep 17 00:00:00 2001 >From: Gary Lockyer <gary@catalyst.net.nz> >Date: Mon, 7 Aug 2017 13:42:02 +1200 >Subject: [PATCH 4/7] samba-tool dns: Test support of DNS wild card in names > >As DNS wild cards are now supported we need to allow '*' characters in >the domain names. > >Signed-off-by: Gary Lockyer <gary@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Garming Sam <garming@catalyst.net.nz> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12952 >(cherry picked from commit 3d2bd849f119480f0c1262c00e45179ceaa6e755) >--- > python/samba/tests/samba_tool/dnscmd.py | 67 +++++++++++++++++++++++++++++++++ > selftest/knownfail.d/sambatooldns | 3 ++ > 2 files changed, 70 insertions(+) > create mode 100644 selftest/knownfail.d/sambatooldns > >diff --git a/python/samba/tests/samba_tool/dnscmd.py b/python/samba/tests/samba_tool/dnscmd.py >index 3a369d9..1712c0e 100644 >--- a/python/samba/tests/samba_tool/dnscmd.py >+++ b/python/samba/tests/samba_tool/dnscmd.py >@@ -659,3 +659,70 @@ class DnsCmdTestCase(SambaToolCmdTest): > self.zone, "testrecord2", > "A", self.testip, self.creds_string) > self.assertCmdFail(result) >+ >+ def test_dns_wildcards(self): >+ """ >+ Ensure that DNS wild card entries can be added deleted and queried >+ """ >+ num_failures = 0 >+ failure_msgs = [] >+ records = [("*.", "MISS", "A", "1.1.1.1"), >+ ("*.SAMDOM", "MISS.SAMDOM", "A", "1.1.1.2")] >+ for (name, miss, dnstype, record) in records: >+ try: >+ result, out, err = self.runsubcmd("dns", "add", >+ os.environ["SERVER"], >+ self.zone, name, >+ dnstype, record, >+ self.creds_string) >+ self.assertCmdSuccess( >+ result, >+ out, >+ err, >+ ("Failed to add record %s (%s) with type %s." >+ % (name, record, dnstype))) >+ >+ result, out, err = self.runsubcmd("dns", "query", >+ os.environ["SERVER"], >+ self.zone, name, >+ dnstype, >+ self.creds_string) >+ self.assertCmdSuccess( >+ result, >+ out, >+ err, >+ ("Failed to query record %s with qualifier %s." >+ % (record, dnstype))) >+ >+ # dns tool does not perform dns wildcard search if the name >+ # does not match >+ result, out, err = self.runsubcmd("dns", "query", >+ os.environ["SERVER"], >+ self.zone, miss, >+ dnstype, >+ self.creds_string) >+ self.assertCmdFail( >+ result, >+ ("Failed to query record %s with qualifier %s." >+ % (record, dnstype))) >+ >+ result, out, err = self.runsubcmd("dns", "delete", >+ os.environ["SERVER"], >+ self.zone, name, >+ dnstype, record, >+ self.creds_string) >+ self.assertCmdSuccess( >+ result, >+ out, >+ err, >+ ("Failed to remove record %s with type %s." >+ % (record, dnstype))) >+ except AssertionError as e: >+ num_failures = num_failures + 1 >+ failure_msgs.append(e) >+ >+ if num_failures > 0: >+ for msg in failure_msgs: >+ print(msg) >+ self.fail("Failed to accept valid commands. %d total failures." >+ "Errors above." % num_failures) >diff --git a/selftest/knownfail.d/sambatooldns b/selftest/knownfail.d/sambatooldns >new file mode 100644 >index 0000000..b60e9b2 >--- /dev/null >+++ b/selftest/knownfail.d/sambatooldns >@@ -0,0 +1,3 @@ >+# Support for DNS wildcared entries by samba_tool dns sub command >+# Will fail until implemented. >+^samba.tests.samba_tool.dnscmd.samba.tests.samba_tool.dnscmd.DnsCmdTestCase.test_dns_wildcards\(ad_dc:local\) >-- >1.9.1 > > >From d74731e2a06a20129ba490bf31409b2c320a4a23 Mon Sep 17 00:00:00 2001 >From: Gary Lockyer <gary@catalyst.net.nz> >Date: Thu, 20 Jul 2017 09:13:43 +1200 >Subject: [PATCH 5/7] samba-tool dns query: Allow '*' in names > >As DNS wild cards are now supported we need to allow '*' characters in >the domain names. > >Signed-off-by: Gary Lockyer <gary@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Garming Sam <garming@catalyst.net.nz> >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12952 >(cherry picked from commit 29b3a2b0d1e5abc1ca9f112f680251e34fa6e3af) >--- > python/samba/netcmd/dns.py | 3 ++- > selftest/knownfail.d/sambatooldns | 3 --- > 2 files changed, 2 insertions(+), 4 deletions(-) > delete mode 100644 selftest/knownfail.d/sambatooldns > >diff --git a/python/samba/netcmd/dns.py b/python/samba/netcmd/dns.py >index 6f88817..fd8db93 100644 >--- a/python/samba/netcmd/dns.py >+++ b/python/samba/netcmd/dns.py >@@ -819,7 +819,8 @@ class cmd_query(Command): > record_type = dns_type_flag(rtype) > > if name.find('*') != -1: >- raise CommandError('Wildcard searches not supported. To dump entire zone use "@"') >+ self.outf.write('use "@" to dump entire domain, looking up %s\n' % >+ name) > > select_flags = 0 > if authority: >diff --git a/selftest/knownfail.d/sambatooldns b/selftest/knownfail.d/sambatooldns >deleted file mode 100644 >index b60e9b2..0000000 >--- a/selftest/knownfail.d/sambatooldns >+++ /dev/null >@@ -1,3 +0,0 @@ >-# Support for DNS wildcared entries by samba_tool dns sub command >-# Will fail until implemented. >-^samba.tests.samba_tool.dnscmd.samba.tests.samba_tool.dnscmd.DnsCmdTestCase.test_dns_wildcards\(ad_dc:local\) >-- >1.9.1 > > >From cea9e5733e79bce7472b2d6765d1fd6029ad4e76 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Tue, 29 Aug 2017 11:48:46 +1200 >Subject: [PATCH 6/7] s4-dnsserver: Always encode user-supplied names when > looking up DNS records > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12994 > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Garming Sam <garming@catalyst.net.nz> >(cherry picked from commit c17470210792e6443bd3c28c18874645f1558494) >--- > source4/rpc_server/dnsserver/dcerpc_dnsserver.c | 15 ++++++++++++--- > source4/rpc_server/dnsserver/dnsdb.c | 15 +++++++++++---- > 2 files changed, 23 insertions(+), 7 deletions(-) > >diff --git a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c >index 286da18..120d4b9 100644 >--- a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c >+++ b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c >@@ -1674,10 +1674,13 @@ static WERROR dnsserver_enumerate_root_records(struct dnsserver_state *dsstate, > /* Add any additional records */ > if (select_flag & DNS_RPC_VIEW_ADDITIONAL_DATA) { > for (i=0; i<add_count; i++) { >+ char *encoded_name >+ = ldb_binary_encode_string(tmp_ctx, >+ add_names[i]); > ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z->zone_dn, > LDB_SCOPE_ONELEVEL, attrs, > "(&(objectClass=dnsNode)(name=%s)(!(dNSTombstoned=TRUE)))", >- add_names[i]); >+ encoded_name); > if (ret != LDB_SUCCESS || res->count == 0) { > talloc_free(res); > continue; >@@ -1744,10 +1747,12 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, > LDB_SCOPE_ONELEVEL, attrs, > "(&(objectClass=dnsNode)(!(dNSTombstoned=TRUE)))"); > } else { >+ char *encoded_name >+ = ldb_binary_encode_string(tmp_ctx, name); > ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z->zone_dn, > LDB_SCOPE_ONELEVEL, attrs, > "(&(objectClass=dnsNode)(|(name=%s)(name=*.%s))(!(dNSTombstoned=TRUE)))", >- name, name); >+ encoded_name, encoded_name); > } > if (ret != LDB_SUCCESS) { > talloc_free(tmp_ctx); >@@ -1818,11 +1823,15 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, > > /* Search all the available zones for additional name */ > for (z2 = dsstate->zones; z2; z2 = z2->next) { >+ char *encoded_name; > name = dns_split_node_name(tmp_ctx, add_names[i], z2->name); >+ encoded_name >+ = ldb_binary_encode_string(tmp_ctx, >+ name); > ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z2->zone_dn, > LDB_SCOPE_ONELEVEL, attrs, > "(&(objectClass=dnsNode)(name=%s)(!(dNSTombstoned=TRUE)))", >- name); >+ encoded_name); > talloc_free(name); > if (ret != LDB_SUCCESS) { > continue; >diff --git a/source4/rpc_server/dnsserver/dnsdb.c b/source4/rpc_server/dnsserver/dnsdb.c >index da37878..15fe565 100644 >--- a/source4/rpc_server/dnsserver/dnsdb.c >+++ b/source4/rpc_server/dnsserver/dnsdb.c >@@ -364,10 +364,12 @@ WERROR dnsserver_db_add_empty_node(TALLOC_CTX *mem_ctx, > const char * const attrs[] = { "name", NULL }; > struct ldb_result *res; > struct ldb_dn *dn; >+ char *encoded_name = ldb_binary_encode_string(mem_ctx, name); > int ret; > > ret = ldb_search(samdb, mem_ctx, &res, z->zone_dn, LDB_SCOPE_BASE, attrs, >- "(&(objectClass=dnsNode)(name=%s))", name); >+ "(&(objectClass=dnsNode)(name=%s))", >+ encoded_name); > if (ret != LDB_SUCCESS) { > return WERR_INTERNAL_DB_ERROR; > } >@@ -406,6 +408,7 @@ WERROR dnsserver_db_add_record(TALLOC_CTX *mem_ctx, > int serial; > WERROR werr; > bool was_tombstoned = false; >+ char *encoded_name = ldb_binary_encode_string(mem_ctx, name); > > werr = dns_to_dnsp_convert(mem_ctx, add_record, &rec, true); > if (!W_ERROR_IS_OK(werr)) { >@@ -436,7 +439,8 @@ WERROR dnsserver_db_add_record(TALLOC_CTX *mem_ctx, > rec->dwTimeStamp = t; > > ret = ldb_search(samdb, mem_ctx, &res, z->zone_dn, LDB_SCOPE_ONELEVEL, attrs, >- "(&(objectClass=dnsNode)(name=%s))", name); >+ "(&(objectClass=dnsNode)(name=%s))", >+ encoded_name); > if (ret != LDB_SUCCESS) { > return WERR_INTERNAL_DB_ERROR; > } >@@ -524,6 +528,7 @@ WERROR dnsserver_db_update_record(TALLOC_CTX *mem_ctx, > int ret, i; > int serial; > WERROR werr; >+ char *encoded_name = ldb_binary_encode_string(mem_ctx, name); > > werr = dns_to_dnsp_convert(mem_ctx, add_record, &arec, true); > if (!W_ERROR_IS_OK(werr)) { >@@ -541,7 +546,8 @@ WERROR dnsserver_db_update_record(TALLOC_CTX *mem_ctx, > arec->dwTimeStamp = t; > > ret = ldb_search(samdb, mem_ctx, &res, z->zone_dn, LDB_SCOPE_ONELEVEL, attrs, >- "(&(objectClass=dnsNode)(name=%s)(!(dNSTombstoned=TRUE)))", name); >+ "(&(objectClass=dnsNode)(name=%s)(!(dNSTombstoned=TRUE)))", >+ encoded_name); > if (ret != LDB_SUCCESS) { > return WERR_INTERNAL_DB_ERROR; > } >@@ -642,7 +648,8 @@ WERROR dnsserver_db_delete_record(TALLOC_CTX *mem_ctx, > } > > ret = ldb_search(samdb, mem_ctx, &res, z->zone_dn, LDB_SCOPE_ONELEVEL, attrs, >- "(&(objectClass=dnsNode)(name=%s))", name); >+ "(&(objectClass=dnsNode)(name=%s))", >+ ldb_binary_encode_string(mem_ctx, name)); > if (ret != LDB_SUCCESS) { > return WERR_INTERNAL_DB_ERROR; > } >-- >1.9.1 > > >From 9eb8e8ce5dbe5badcbdd57cc1040a43124531bb1 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Tue, 29 Aug 2017 14:19:22 +1200 >Subject: [PATCH 7/7] s4-dnsserver: Check for too many DNS results > >If we had this check in when the wildcard DNS tests were written, we would have >noticed that the name needed to be escaped (see previous commit). > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12994 >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz> >Reviewed-by: Garming Sam <garming@catalyst.net.nz> >(cherry picked from commit 9e9a8d8f887a3b13d06a7cc71edad78c140bb0be) >--- > source4/rpc_server/dnsserver/dnsdb.c | 3 +++ > 1 file changed, 3 insertions(+) > >diff --git a/source4/rpc_server/dnsserver/dnsdb.c b/source4/rpc_server/dnsserver/dnsdb.c >index 15fe565..81a2d20 100644 >--- a/source4/rpc_server/dnsserver/dnsdb.c >+++ b/source4/rpc_server/dnsserver/dnsdb.c >@@ -657,6 +657,9 @@ WERROR dnsserver_db_delete_record(TALLOC_CTX *mem_ctx, > if (res->count == 0) { > return WERR_DNS_ERROR_RECORD_DOES_NOT_EXIST; > } >+ if (res->count > 1) { >+ return WERR_DNS_ERROR_RCODE_SERVER_FAILURE; >+ } > > el = ldb_msg_find_element(res->msgs[0], "dnsRecord"); > if (el == NULL || el->num_values == 0) { >-- >1.9.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
abartlet
:
review+
Actions:
View
Attachments on
bug 12952
:
13453
| 13706