Commit 993b086d authored by Grigorii Demidov's avatar Grigorii Demidov Committed by Vladimír Čunát

layer/validate: forwarding mode, another CNAME fix

Don't check proof of nonexistance in NODATA or NAME ERROR answers
which contains a CNAME.
parent 62b49006
......@@ -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 */
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment