]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
CVE-2018-14629 dns: fix CNAME loop prevention using counter regression
authorStefan Metzmacher <metze@samba.org>
Wed, 28 Nov 2018 14:21:56 +0000 (15:21 +0100)
committerKarolin Seeger <kseeger@samba.org>
Fri, 7 Dec 2018 15:59:16 +0000 (16:59 +0100)
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

(cherry picked from commit 34f4491d79b47b2fe2457b8882f11644cf773bc4)

Autobuild-User(v4-7-test): Karolin Seeger <kseeger@samba.org>
Autobuild-Date(v4-7-test): Fri Dec  7 16:59:16 CET 2018 on sn-devel-144

selftest/knownfail.d/dns
source4/dns_server/dns_query.c

index bd12d439c116dc9ff6d5e90da529b1c9e733f4ec..c26a31aeb4e147a244094b561cdbb6cd17f35f5e 100644 (file)
@@ -61,9 +61,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
index fafadb6ac6f2c1234c766241c7d47727b145f080..cb9afd099c2f44a74716765b5e86bcd6acd88fae 100644 (file)
@@ -439,7 +439,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 {
@@ -455,7 +456,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;
@@ -471,7 +473,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);
        }
@@ -516,7 +518,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);
                }
@@ -600,6 +603,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);
@@ -608,7 +613,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;
@@ -626,6 +632,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)) {
@@ -646,7 +653,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);
        }
@@ -678,7 +686,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;
        }
@@ -1050,7 +1059,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);
                }
@@ -1152,7 +1162,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;