summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Haslett <aaronhaslett@catalyst.net.nz>2018-10-23 17:25:51 +1300
committerKarolin Seeger <kseeger@samba.org>2018-11-26 09:38:10 +0100
commitf7a8294d65e5a7424da93499074a30cb65418ce7 (patch)
treee236e19ed9619d96ea43859660aa2aff35842e59
parent322992344246a880430de38c27aabc6135a85147 (diff)
downloadsamba-f7a8294d65e5a7424da93499074a30cb65418ce7.tar.gz
CVE-2018-14629 dns: CNAME loop prevention using counter
Count number of answers generated by internal DNS query routine and stop at 20 to match Microsoft's loop prevention mechanism. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13600 Signed-off-by: Aaron Haslett <aaronhaslett@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Garming Sam <garming@catalyst.net.nz>
-rw-r--r--python/samba/tests/dns.py24
-rw-r--r--selftest/knownfail.d/dns6
-rw-r--r--source4/dns_server/dns_query.c6
3 files changed, 36 insertions, 0 deletions
diff --git a/python/samba/tests/dns.py b/python/samba/tests/dns.py
index 1b5b64da3a4..3390a3990c9 100644
--- a/python/samba/tests/dns.py
+++ b/python/samba/tests/dns.py
@@ -798,6 +798,30 @@ class TestComplexQueries(DNSTest):
self.assertEquals(response.answers[1].name, name2)
self.assertEquals(response.answers[1].rdata, name0)
+ def test_cname_loop(self):
+ cname1 = "cnamelooptestrec." + self.get_dns_domain()
+ cname2 = "cnamelooptestrec2." + self.get_dns_domain()
+ cname3 = "cnamelooptestrec3." + self.get_dns_domain()
+ self.make_dns_update(cname1, cname2, dnsp.DNS_TYPE_CNAME)
+ self.make_dns_update(cname2, cname3, dnsp.DNS_TYPE_CNAME)
+ self.make_dns_update(cname3, cname1, dnsp.DNS_TYPE_CNAME)
+
+ p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
+ questions = []
+
+ q = self.make_name_question(cname1,
+ 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)
+
+ max_recursion_depth = 20
+ self.assertEquals(len(response.answers), max_recursion_depth)
+
+
class TestInvalidQueries(DNSTest):
def setUp(self):
super(TestInvalidQueries, self).setUp()
diff --git a/selftest/knownfail.d/dns b/selftest/knownfail.d/dns
index cb3003240ea..8c79b3abe00 100644
--- a/selftest/knownfail.d/dns
+++ b/selftest/knownfail.d/dns
@@ -45,3 +45,9 @@ samba.tests.dns.__main__.TestSimpleQueries.test_qtype_all_query\(rodc:local\)
# The SOA override should not pass against the RODC, it must not overstamp
samba.tests.dns.__main__.TestSimpleQueries.test_one_SOA_query\(rodc:local\)
+
+#
+# rodc and vampire_dc require signed dns updates, so the test setup
+# fails, but the test does run on fl2003dc
+^samba.tests.dns.__main__.TestComplexQueries.test_cname_loop\(rodc:local\)
+^samba.tests.dns.__main__.TestComplexQueries.test_cname_loop\(vampire_dc:local\)
diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c
index e8de304c8bb..fafadb6ac6f 100644
--- a/source4/dns_server/dns_query.c
+++ b/source4/dns_server/dns_query.c
@@ -40,6 +40,7 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_DNS
+#define MAX_Q_RECURSION_DEPTH 20
struct forwarder_string {
const char *forwarder;
@@ -470,6 +471,11 @@ static struct tevent_req *handle_dnsrpcrec_send(
state->answers = answers;
state->nsrecs = nsrecs;
+ if (talloc_array_length(*answers) >= MAX_Q_RECURSION_DEPTH) {
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
+ }
+
resolve_cname = ((rec->wType == DNS_TYPE_CNAME) &&
((question->question_type == DNS_QTYPE_A) ||
(question->question_type == DNS_QTYPE_AAAA)));