mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
dnssec lameness detection improved to disable detection when not sure.
git-svn-id: file:///svn/unbound/trunk@715 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
633daf4bc7
commit
f92d51b3fe
7 changed files with 110 additions and 11 deletions
|
|
@ -1,3 +1,9 @@
|
||||||
|
23 October 2007: Wouter
|
||||||
|
- fixup (grand-)parent problem for dnssec-lameness detection.
|
||||||
|
- fixup tests to do additional section processing for lame replies,
|
||||||
|
since the detection needs that.
|
||||||
|
- no longer trust in query section in reply during dnssec lame detect.
|
||||||
|
|
||||||
22 October 2007: Wouter
|
22 October 2007: Wouter
|
||||||
- added donotquerylocalhost config option. Can be turned off for
|
- added donotquerylocalhost config option. Can be turned off for
|
||||||
out test cases.
|
out test cases.
|
||||||
|
|
|
||||||
|
|
@ -140,3 +140,22 @@ o The method by which dnssec-lameness is detected is not secure. DNSSEC lame
|
||||||
Also for zones for which no chain of trust exists, but a DS is given by the
|
Also for zones for which no chain of trust exists, but a DS is given by the
|
||||||
parent, dnssec-lameness detection enables. This delivers dnnsec to our
|
parent, dnssec-lameness detection enables. This delivers dnnsec to our
|
||||||
clients when possible (for client validators).
|
clients when possible (for client validators).
|
||||||
|
|
||||||
|
The following issue needs to be resolved:
|
||||||
|
a server that serves both a parent and child zone, where
|
||||||
|
parent is signed, but child is not. The server must not be marked
|
||||||
|
lame for the parent zone, because the child answer is not signed.
|
||||||
|
Instead of a false positive, we want false negatives; failure to
|
||||||
|
detect dnssec-lameness is less of a problem than marking honest
|
||||||
|
servers lame. dnssec-lameness is a config error and deserves the trouble.
|
||||||
|
So, only messages that identify the zone are used to mark the zone
|
||||||
|
lame. The zone is identified by SOA or NS RRsets in the answer/auth.
|
||||||
|
That includes almost all negative responses and also A, AAAA qtypes.
|
||||||
|
That would be most responses from servers.
|
||||||
|
For referrals, delegations that add a single label can be checked to be
|
||||||
|
from their zone, this covers most delegation-centric zones.
|
||||||
|
|
||||||
|
So possibly, for complicated setups, with multiple (parent-child) zones
|
||||||
|
on a server, dnssec-lameness detection does not work - no dnssec-lameness
|
||||||
|
is detected. Instead the zone that is dnssec-lame becomes bogus.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -371,18 +371,18 @@ iter_dp_is_useless(struct module_qstate* qstate, struct delegpt* dp)
|
||||||
|
|
||||||
int
|
int
|
||||||
iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
|
iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
|
||||||
struct dns_msg* msg)
|
struct dns_msg* msg, uint16_t dclass)
|
||||||
{
|
{
|
||||||
/* information not available, !env->anchors can be common */
|
/* information not available, !env->anchors can be common */
|
||||||
if(!env || !env->anchors || !dp || !dp->name || !msg || !msg->rep)
|
if(!env || !env->anchors || !dp || !dp->name || !msg || !msg->rep)
|
||||||
return 0;
|
return 0;
|
||||||
/* a trust anchor exists with this name, RRSIGs expected */
|
/* a trust anchor exists with this name, RRSIGs expected */
|
||||||
if(anchor_find(env->anchors, dp->name, dp->namelabs, dp->namelen,
|
if(anchor_find(env->anchors, dp->name, dp->namelabs, dp->namelen,
|
||||||
msg->qinfo.qclass))
|
dclass))
|
||||||
return 1;
|
return 1;
|
||||||
/* see if DS rrset was given, in AUTH section */
|
/* see if DS rrset was given, in AUTH section */
|
||||||
if(reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen,
|
if(reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen,
|
||||||
LDNS_RR_TYPE_DS, msg->qinfo.qclass))
|
LDNS_RR_TYPE_DS, dclass))
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -402,3 +402,45 @@ iter_msg_has_dnssec(struct dns_msg* msg)
|
||||||
* not empty (NSEC) */
|
* not empty (NSEC) */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int iter_msg_from_zone(struct dns_msg* msg, struct delegpt* dp,
|
||||||
|
enum response_type type, uint16_t dclass)
|
||||||
|
{
|
||||||
|
if(!msg || !dp || !msg->rep || !dp->name)
|
||||||
|
return 0;
|
||||||
|
/* SOA RRset - always from reply zone */
|
||||||
|
if(reply_find_rrset_section_an(msg->rep, dp->name, dp->namelen,
|
||||||
|
LDNS_RR_TYPE_SOA, dclass) ||
|
||||||
|
reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen,
|
||||||
|
LDNS_RR_TYPE_SOA, dclass))
|
||||||
|
return 1;
|
||||||
|
if(type == RESPONSE_TYPE_REFERRAL) {
|
||||||
|
size_t i;
|
||||||
|
/* if it adds a single label, i.e. we expect .com,
|
||||||
|
* and referral to example.com. NS ... , then origin zone
|
||||||
|
* is .com. For a referral to sub.example.com. NS ... then
|
||||||
|
* we do not know, since example.com. may be in between. */
|
||||||
|
for(i=0; i<msg->rep->an_numrrsets+msg->rep->ns_numrrsets;
|
||||||
|
i++) {
|
||||||
|
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
|
||||||
|
if(ntohs(s->rk.type) == LDNS_RR_TYPE_NS &&
|
||||||
|
ntohs(s->rk.rrset_class) == dclass) {
|
||||||
|
int l = dname_count_labels(s->rk.dname);
|
||||||
|
if(l == dp->namelabs + 1 &&
|
||||||
|
dname_strict_subdomain(s->rk.dname,
|
||||||
|
l, dp->name, dp->namelabs))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
log_assert(type==RESPONSE_TYPE_ANSWER || type==RESPONSE_TYPE_CNAME);
|
||||||
|
/* not a referral, and not lame delegation (upwards), so,
|
||||||
|
* any NS rrset must be from the zone itself */
|
||||||
|
if(reply_find_rrset_section_an(msg->rep, dp->name, dp->namelen,
|
||||||
|
LDNS_RR_TYPE_NS, dclass) ||
|
||||||
|
reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen,
|
||||||
|
LDNS_RR_TYPE_NS, dclass))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@
|
||||||
|
|
||||||
#ifndef ITERATOR_ITER_UTILS_H
|
#ifndef ITERATOR_ITER_UTILS_H
|
||||||
#define ITERATOR_ITER_UTILS_H
|
#define ITERATOR_ITER_UTILS_H
|
||||||
|
#include "iterator/iter_resptype.h"
|
||||||
struct iter_env;
|
struct iter_env;
|
||||||
struct config_file;
|
struct config_file;
|
||||||
struct module_env;
|
struct module_env;
|
||||||
|
|
@ -143,10 +144,11 @@ int iter_dp_is_useless(struct module_qstate* qstate, struct delegpt* dp);
|
||||||
* @param env: module env with trust anchors.
|
* @param env: module env with trust anchors.
|
||||||
* @param dp: delegation point.
|
* @param dp: delegation point.
|
||||||
* @param msg: delegation message, with DS if a secure referral.
|
* @param msg: delegation message, with DS if a secure referral.
|
||||||
|
* @param dclass: class of query.
|
||||||
* @return 1 if dnssec is expected, 0 if not.
|
* @return 1 if dnssec is expected, 0 if not.
|
||||||
*/
|
*/
|
||||||
int iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
|
int iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
|
||||||
struct dns_msg* msg);
|
struct dns_msg* msg, uint16_t dclass);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See if a message contains DNSSEC.
|
* See if a message contains DNSSEC.
|
||||||
|
|
@ -158,4 +160,19 @@ int iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
|
||||||
*/
|
*/
|
||||||
int iter_msg_has_dnssec(struct dns_msg* msg);
|
int iter_msg_has_dnssec(struct dns_msg* msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See if a message is known to be from a certain zone.
|
||||||
|
* This looks for SOA or NS rrsets, for answers.
|
||||||
|
* For referrals, when one label is delegated, the zone is detected.
|
||||||
|
* Does not look at signatures.
|
||||||
|
* @param msg: the message to inspect.
|
||||||
|
* @param dp: delegation point with zone name to look for.
|
||||||
|
* @param type: type of message.
|
||||||
|
* @param dclass: class of query.
|
||||||
|
* @return true if message is certain to be from zone in dp->name.
|
||||||
|
* false if not sure (empty msg), or not from the zone.
|
||||||
|
*/
|
||||||
|
int iter_msg_from_zone(struct dns_msg* msg, struct delegpt* dp,
|
||||||
|
enum response_type type, uint16_t dclass);
|
||||||
|
|
||||||
#endif /* ITERATOR_ITER_UTILS_H */
|
#endif /* ITERATOR_ITER_UTILS_H */
|
||||||
|
|
|
||||||
|
|
@ -804,7 +804,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||||
/* if the cache reply dp equals a validation anchor or msg has DS,
|
/* if the cache reply dp equals a validation anchor or msg has DS,
|
||||||
* then DNSSEC RRSIGs are expected in the reply */
|
* then DNSSEC RRSIGs are expected in the reply */
|
||||||
iq->dnssec_expected = iter_indicates_dnssec(qstate->env, iq->dp,
|
iq->dnssec_expected = iter_indicates_dnssec(qstate->env, iq->dp,
|
||||||
iq->deleg_msg);
|
iq->deleg_msg, iq->qchase.qclass);
|
||||||
|
|
||||||
/* Reset the RD flag. If this is a query restart, then the RD
|
/* Reset the RD flag. If this is a query restart, then the RD
|
||||||
* will have been turned off. */
|
* will have been turned off. */
|
||||||
|
|
@ -1192,12 +1192,18 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||||
* differently. No queries should be sent elsewhere */
|
* differently. No queries should be sent elsewhere */
|
||||||
type = RESPONSE_TYPE_ANSWER;
|
type = RESPONSE_TYPE_ANSWER;
|
||||||
}
|
}
|
||||||
if(!(iq->chase_flags&BIT_RD) && type != RESPONSE_TYPE_LAME &&
|
if(iq->dnssec_expected && !(iq->chase_flags&BIT_RD)
|
||||||
type != RESPONSE_TYPE_THROWAWAY &&
|
&& type != RESPONSE_TYPE_LAME
|
||||||
type != RESPONSE_TYPE_UNTYPED && iq->dnssec_expected) {
|
&& type != RESPONSE_TYPE_THROWAWAY
|
||||||
|
&& type != RESPONSE_TYPE_UNTYPED) {
|
||||||
/* a possible answer, see if it is missing DNSSEC */
|
/* a possible answer, see if it is missing DNSSEC */
|
||||||
/* but not when forwarding, so we dont mark fwder lame */
|
/* but not when forwarding, so we dont mark fwder lame */
|
||||||
if(!iter_msg_has_dnssec(iq->response))
|
/* also make sure the answer is from the zone we expected,
|
||||||
|
* otherwise, (due to parent,child on same server), we
|
||||||
|
* might mark the server,zone lame inappropriately */
|
||||||
|
if(!iter_msg_has_dnssec(iq->response) &&
|
||||||
|
iter_msg_from_zone(iq->response, iq->dp, type,
|
||||||
|
iq->qchase.qclass))
|
||||||
type = RESPONSE_TYPE_LAME;
|
type = RESPONSE_TYPE_LAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1242,7 +1248,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||||
/* see if the next dp is a trust anchor, or a DS was sent
|
/* see if the next dp is a trust anchor, or a DS was sent
|
||||||
* along, indicating dnssec is expected for next zone */
|
* along, indicating dnssec is expected for next zone */
|
||||||
iq->dnssec_expected = iter_indicates_dnssec(qstate->env,
|
iq->dnssec_expected = iter_indicates_dnssec(qstate->env,
|
||||||
iq->dp, iq->response);
|
iq->dp, iq->response, iq->qchase.qclass);
|
||||||
|
|
||||||
/* stop current outstanding queries.
|
/* stop current outstanding queries.
|
||||||
* FIXME: should the outstanding queries be waited for and
|
* FIXME: should the outstanding queries be waited for and
|
||||||
|
|
|
||||||
5
testdata/iter_dnsseclame_ds.rpl
vendored
5
testdata/iter_dnsseclame_ds.rpl
vendored
|
|
@ -270,12 +270,15 @@ www.sub.example.com. IN A
|
||||||
SECTION ANSWER
|
SECTION ANSWER
|
||||||
www.sub.example.com. IN A 11.11.11.11
|
www.sub.example.com. IN A 11.11.11.11
|
||||||
SECTION AUTHORITY
|
SECTION AUTHORITY
|
||||||
|
; dnssec-lameness detection depends on this information
|
||||||
|
sub.example.com. IN NS ns.sub.example.com.
|
||||||
|
sub.example.com. IN NS ns.example.net.
|
||||||
SECTION ADDITIONAL
|
SECTION ADDITIONAL
|
||||||
|
ns.sub.example.com. IN A 1.2.3.6
|
||||||
ENTRY_END
|
ENTRY_END
|
||||||
RANGE_END
|
RANGE_END
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
STEP 1 QUERY
|
STEP 1 QUERY
|
||||||
ENTRY_BEGIN
|
ENTRY_BEGIN
|
||||||
REPLY RD DO
|
REPLY RD DO
|
||||||
|
|
|
||||||
6
testdata/iter_dnsseclame_ta.rpl
vendored
6
testdata/iter_dnsseclame_ta.rpl
vendored
|
|
@ -204,6 +204,12 @@ www.example.com. IN A
|
||||||
SECTION ANSWER
|
SECTION ANSWER
|
||||||
; the wrong answer.
|
; the wrong answer.
|
||||||
www.example.com. IN A 10.20.30.40
|
www.example.com. IN A 10.20.30.40
|
||||||
|
SECTION AUTHORITY
|
||||||
|
; dnssec-lameness detection depends on this information
|
||||||
|
example.com. IN NS ns.example.com.
|
||||||
|
example.com. IN NS ns.example.net.
|
||||||
|
SECTION ADDITIONAL
|
||||||
|
ns.example.com. IN A 1.2.3.55
|
||||||
ENTRY_END
|
ENTRY_END
|
||||||
RANGE_END
|
RANGE_END
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue