]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
layer/validate: forwarding mode, another CNAME fix
authorGrigorii Demidov <grigorii.demidov@nic.cz>
Wed, 21 Jun 2017 08:02:13 +0000 (10:02 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Wed, 21 Jun 2017 13:21:10 +0000 (15:21 +0200)
Don't check proof of nonexistance in NODATA or NAME ERROR answers
which contains a CNAME.

lib/layer/iterate.c
lib/layer/validate.c

index 11ae80d91b343c8af08807c48b2b2a92d035f7d0..b8ce5d01a40779d221e40a173229547695059fdd 100644 (file)
@@ -449,6 +449,7 @@ static int unroll_cname(knot_pkt_t *pkt, struct kr_request *req, bool referral,
                 * Try to find records for pending_cname owner from section start. */
                cname = pending_cname;
                pending_cname = NULL;
+               const int cname_labels = knot_dname_labels(cname, NULL);
                for (unsigned i = 0; i < an->count; ++i) {
                        const knot_rrset_t *rr = knot_pkt_rr(an, i);
 
@@ -461,6 +462,16 @@ static int unroll_cname(knot_pkt_t *pkt, struct kr_request *req, bool referral,
                                continue;
                        }
 
+                       if (rr->type == KNOT_RRTYPE_RRSIG) {
+                               int rrsig_labels = knot_rrsig_labels(&rr->rrs, 0);
+                               if (rrsig_labels > cname_labels) {
+                                       return KR_STATE_FAIL;
+                               }
+                               if (rrsig_labels < cname_labels) {
+                                       query->flags |= QUERY_DNSSEC_WEXPAND;
+                               }
+                       }
+
                        /* Process records matching current SNAME */
                        int state = KR_STATE_FAIL;
                        bool to_wire = false;
@@ -509,7 +520,6 @@ static int unroll_cname(knot_pkt_t *pkt, struct kr_request *req, bool referral,
                }
                /* try to unroll cname only within current zone */
                const int pending_labels = knot_dname_labels(pending_cname, NULL);
-               const int cname_labels = knot_dname_labels(cname, NULL);
                if (pending_labels != cname_labels) {
                        cname = pending_cname;
                        break;
@@ -675,9 +685,12 @@ static int process_answer(knot_pkt_t *pkt, struct kr_request *req)
                } else {
                        next->flags &= ~QUERY_DNSSEC_WANT;
                }
-               state = pick_authority(pkt, req, false);
-               if (state != kr_ok()) {
-                       return KR_STATE_FAIL;
+               if (!(query->flags & QUERY_FORWARD) ||
+                   (query->flags & QUERY_DNSSEC_WEXPAND)) {
+                       state = pick_authority(pkt, req, false);
+                       if (state != kr_ok()) {
+                               return KR_STATE_FAIL;
+                       }
                }
        } else if (!query->parent) {
                /* Answer for initial query */
index 68d0323a0f33797caddd4d86ab9c7e6adcffe165..66e16f08cf27a24f56a70fc0d0f85f69b6917648 100644 (file)
@@ -590,7 +590,7 @@ static int unsigned_forward(kr_layer_t *ctx, knot_pkt_t *pkt)
                }
        }
 
-       if (nods && ns_exist && qtype == KNOT_RRTYPE_NS && !(qry->flags & QUERY_CNAME)) {
+       if (nods && ns_exist && qtype == KNOT_RRTYPE_NS) {
                qry->flags &= ~QUERY_DNSSEC_WANT;
                qry->flags |= QUERY_DNSSEC_INSECURE;
                if (qry->forward_flags & QUERY_CNAME) {
@@ -859,7 +859,6 @@ static int validate(kr_layer_t *ctx, knot_pkt_t *pkt)
        bool has_nsec3 = pkt_has_type(pkt, KNOT_RRTYPE_NSEC3);
        const knot_pktsection_t *an = knot_pkt_section(pkt, KNOT_ANSWER);
        const bool referral = (an->count == 0 && !knot_wire_get_aa(pkt->wire));
-       const bool no_data = (an->count == 0 && knot_wire_get_aa(pkt->wire));
 
        if (!(qry->flags & QUERY_CACHED) && knot_wire_get_aa(pkt->wire)) {
                /* Check if answer if not empty,
@@ -896,7 +895,8 @@ static int validate(kr_layer_t *ctx, knot_pkt_t *pkt)
        }
 
        /* Validate non-existence proof if not positive answer. */
-       if (!(qry->flags & QUERY_CACHED) && pkt_rcode == KNOT_RCODE_NXDOMAIN) {
+       if (!(qry->flags & QUERY_CACHED) && pkt_rcode == KNOT_RCODE_NXDOMAIN &&
+           ((qry->flags & (QUERY_FORWARD | QUERY_CNAME)) != (QUERY_FORWARD | QUERY_CNAME))) {
                /* @todo If knot_pkt_qname(pkt) is used instead of qry->sname then the tests crash. */
                if (!has_nsec3) {
                        ret = kr_nsec_name_error_response_check(pkt, KNOT_AUTHORITY, qry->sname);
@@ -920,8 +920,10 @@ static int validate(kr_layer_t *ctx, knot_pkt_t *pkt)
        /* @todo WTH, this needs API that just tries to find a proof and the caller
         * doesn't have to worry about NSEC/NSEC3
         * @todo rework this */
-       if (!(qry->flags & QUERY_CACHED)) {
-               if (pkt_rcode == KNOT_RCODE_NOERROR && no_data) {
+       if (!(qry->flags & QUERY_CACHED) && (pkt_rcode == KNOT_RCODE_NOERROR) &&
+           ((qry->flags & (QUERY_FORWARD | QUERY_CNAME)) != (QUERY_FORWARD | QUERY_CNAME))) {
+               bool no_data = (an->count == 0 && knot_wire_get_aa(pkt->wire));
+               if (no_data) {
                        /* @todo
                         * ? quick mechanism to determine which check to preform first
                         * ? merge the functionality together to share code/resources