summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2018-11-28 15:21:56 +0100
committerAndrew Bartlett <abartlet@samba.org>2018-12-04 08:52:29 +0100
commit34f4491d79b47b2fe2457b8882f11644cf773bc4 (patch)
treebbe82040201da2de1151ddc741e1af3d95df1925
parent14399fd818b130a6347eec860460929c292d5996 (diff)
downloadsamba-34f4491d79b47b2fe2457b8882f11644cf773bc4.tar.gz
CVE-2018-14629 dns: fix CNAME loop prevention using counter regression
The loop prevention should only be done for CNAME records! Otherwise we truncate the answer records for A, AAAA or SRV queries, which is a bad idea if you have more than 20 DCs. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13600 Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz> Autobuild-User(master): Andrew Bartlett <abartlet@samba.org> Autobuild-Date(master): Tue Dec 4 08:52:29 CET 2018 on sn-devel-144
-rw-r--r--selftest/knownfail.d/dns6
-rw-r--r--source4/dns_server/dns_query.c29
2 files changed, 20 insertions, 15 deletions
diff --git a/selftest/knownfail.d/dns b/selftest/knownfail.d/dns
index 4bf01bdd89e..ec345372046 100644
--- a/selftest/knownfail.d/dns
+++ b/selftest/knownfail.d/dns
@@ -87,9 +87,3 @@ samba.tests.dns.__main__.TestSimpleQueries.test_one_SOA_query\(rodc:local\)
^samba.tests.dns.__main__.TestComplexQueries.test_cname_limit\(rodc:local\)
^samba.tests.dns.__main__.TestComplexQueries.test_cname_any_query\(vampire_dc:local\)
^samba.tests.dns.__main__.TestComplexQueries.test_cname_any_query\(rodc:local\)
-
-# These all fail until the next patch
-^samba.tests.dns.__main__.TestComplexQueries.test_cname_limit
-^samba.tests.dns.__main__.TestComplexQueries.test_record_limit_SRV
-^samba.tests.dns.__main__.TestComplexQueries.test_record_limit_AAAA
-^samba.tests.dns.__main__.TestComplexQueries.test_record_limit_A
diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c
index 65faeac3b6a..b75fabe7e82 100644
--- a/source4/dns_server/dns_query.c
+++ b/source4/dns_server/dns_query.c
@@ -388,7 +388,8 @@ static struct tevent_req *handle_authoritative_send(
TALLOC_CTX *mem_ctx, struct tevent_context *ev,
struct dns_server *dns, const char *forwarder,
struct dns_name_question *question,
- struct dns_res_rec **answers, struct dns_res_rec **nsrecs);
+ struct dns_res_rec **answers, struct dns_res_rec **nsrecs,
+ size_t cname_depth);
static WERROR handle_authoritative_recv(struct tevent_req *req);
struct handle_dnsrpcrec_state {
@@ -404,7 +405,8 @@ static struct tevent_req *handle_dnsrpcrec_send(
struct dns_server *dns, const char *forwarder,
const struct dns_name_question *question,
struct dnsp_DnssrvRpcRecord *rec,
- struct dns_res_rec **answers, struct dns_res_rec **nsrecs)
+ struct dns_res_rec **answers, struct dns_res_rec **nsrecs,
+ size_t cname_depth)
{
struct tevent_req *req, *subreq;
struct handle_dnsrpcrec_state *state;
@@ -420,7 +422,7 @@ static struct tevent_req *handle_dnsrpcrec_send(
state->answers = answers;
state->nsrecs = nsrecs;
- if (talloc_array_length(*answers) >= MAX_Q_RECURSION_DEPTH) {
+ if (cname_depth >= MAX_Q_RECURSION_DEPTH) {
tevent_req_done(req);
return tevent_req_post(req, ev);
}
@@ -465,7 +467,8 @@ static struct tevent_req *handle_dnsrpcrec_send(
if (dns_authoritative_for_zone(dns, new_q->name)) {
subreq = handle_authoritative_send(
state, ev, dns, forwarder, new_q,
- state->answers, state->nsrecs);
+ state->answers, state->nsrecs,
+ cname_depth + 1);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
@@ -549,6 +552,8 @@ struct handle_authoritative_state {
struct dns_res_rec **answers;
struct dns_res_rec **nsrecs;
+
+ size_t cname_depth;
};
static void handle_authoritative_done(struct tevent_req *subreq);
@@ -557,7 +562,8 @@ static struct tevent_req *handle_authoritative_send(
TALLOC_CTX *mem_ctx, struct tevent_context *ev,
struct dns_server *dns, const char *forwarder,
struct dns_name_question *question,
- struct dns_res_rec **answers, struct dns_res_rec **nsrecs)
+ struct dns_res_rec **answers, struct dns_res_rec **nsrecs,
+ size_t cname_depth)
{
struct tevent_req *req, *subreq;
struct handle_authoritative_state *state;
@@ -575,6 +581,7 @@ static struct tevent_req *handle_authoritative_send(
state->forwarder = forwarder;
state->answers = answers;
state->nsrecs = nsrecs;
+ state->cname_depth = cname_depth;
werr = dns_name2dn(dns, state, question->name, &dn);
if (tevent_req_werror(req, werr)) {
@@ -595,7 +602,8 @@ static struct tevent_req *handle_authoritative_send(
subreq = handle_dnsrpcrec_send(
state, state->ev, state->dns, state->forwarder,
state->question, &state->recs[state->recs_done],
- state->answers, state->nsrecs);
+ state->answers, state->nsrecs,
+ state->cname_depth);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
@@ -627,7 +635,8 @@ static void handle_authoritative_done(struct tevent_req *subreq)
subreq = handle_dnsrpcrec_send(
state, state->ev, state->dns, state->forwarder,
state->question, &state->recs[state->recs_done],
- state->answers, state->nsrecs);
+ state->answers, state->nsrecs,
+ state->cname_depth);
if (tevent_req_nomem(subreq, req)) {
return;
}
@@ -1000,7 +1009,8 @@ struct tevent_req *dns_server_process_query_send(
subreq = handle_authoritative_send(
state, ev, dns, (forwarders == NULL ? NULL : forwarders[0]),
- &in->questions[0], &state->answers, &state->nsrecs);
+ &in->questions[0], &state->answers, &state->nsrecs,
+ 0); /* cname_depth */
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
@@ -1102,7 +1112,8 @@ static void dns_server_process_query_got_auth(struct tevent_req *subreq)
subreq = handle_authoritative_send(state, state->ev, state->dns,
state->forwarders->forwarder,
state->question, &state->answers,
- &state->nsrecs);
+ &state->nsrecs,
+ 0); /* cname_depth */
if (tevent_req_nomem(subreq, req)) {
return;