dnssec lame detection.

git-svn-id: file:///svn/unbound/trunk@714 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards
2007-10-22 15:25:37 +00:00
parent b247774236
commit 633daf4bc7
17 changed files with 1189 additions and 27 deletions
+35
View File
@@ -58,6 +58,7 @@
#include "util/data/dname.h"
#include "util/random.h"
#include "util/fptr_wlist.h"
#include "validator/val_anchor.h"
/** fillup fetch policy array */
static void
@@ -367,3 +368,37 @@ iter_dp_is_useless(struct module_qstate* qstate, struct delegpt* dp)
}
return 1;
}
int
iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
struct dns_msg* msg)
{
/* information not available, !env->anchors can be common */
if(!env || !env->anchors || !dp || !dp->name || !msg || !msg->rep)
return 0;
/* a trust anchor exists with this name, RRSIGs expected */
if(anchor_find(env->anchors, dp->name, dp->namelabs, dp->namelen,
msg->qinfo.qclass))
return 1;
/* see if DS rrset was given, in AUTH section */
if(reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen,
LDNS_RR_TYPE_DS, msg->qinfo.qclass))
return 1;
return 0;
}
int
iter_msg_has_dnssec(struct dns_msg* msg)
{
size_t i;
if(!msg || !msg->rep)
return 0;
for(i=0; i<msg->rep->an_numrrsets + msg->rep->ns_numrrsets; i++) {
if(((struct packed_rrset_data*)msg->rep->rrsets[i]->
entry.data)->rrsig_count > 0)
return 1;
}
/* empty message has no DNSSEC info, with DNSSEC the reply is
* not empty (NSEC) */
return 0;
}
+22
View File
@@ -136,4 +136,26 @@ void iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp);
*/
int iter_dp_is_useless(struct module_qstate* qstate, struct delegpt* dp);
/**
* See if delegation is expected to have DNSSEC information (RRSIGs) in
* its answers, or not. Inspects delegation point (name), trust anchors,
* and delegation message (DS RRset) to determine this.
* @param env: module env with trust anchors.
* @param dp: delegation point.
* @param msg: delegation message, with DS if a secure referral.
* @return 1 if dnssec is expected, 0 if not.
*/
int iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
struct dns_msg* msg);
/**
* See if a message contains DNSSEC.
* This is examined by looking for RRSIGs. With DNSSEC a valid answer,
* nxdomain, nodata, referral or cname reply has RRSIGs in answer or auth
* sections, sigs on answer data, SOA, DS, or NSEC/NSEC3 records.
* @param msg: message to examine.
* @return true if DNSSEC information was found.
*/
int iter_msg_has_dnssec(struct dns_msg* msg);
#endif /* ITERATOR_ITER_UTILS_H */
+21 -2
View File
@@ -114,6 +114,7 @@ iter_new(struct module_qstate* qstate, int id)
iq->referral_count = 0;
iq->wait_priming_stub = 0;
iq->refetch_glue = 0;
iq->dnssec_expected = 0;
iq->chase_flags = qstate->query_flags;
/* Start with the (current) qname. */
iq->qchase = qstate->qinfo;
@@ -730,8 +731,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
}
while(1) {
/* Lookup the delegation in the cache. If null, then the cache needs
* to be primed for the qclass. */
/* Lookup the delegation in the cache. If null, then the
* cache needs to be primed for the qclass. */
iq->dp = dns_cache_find_delegation(qstate->env, delname,
delnamelen, iq->qchase.qtype, iq->qchase.qclass,
qstate->region, &iq->deleg_msg, (uint32_t)time(NULL));
@@ -800,6 +801,11 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
verbose(VERB_ALGO, "cache delegation returns delegpt");
delegpt_log(VERB_ALGO, iq->dp);
/* if the cache reply dp equals a validation anchor or msg has DS,
* then DNSSEC RRSIGs are expected in the reply */
iq->dnssec_expected = iter_indicates_dnssec(qstate->env, iq->dp,
iq->deleg_msg);
/* Reset the RD flag. If this is a query restart, then the RD
* will have been turned off. */
if(qstate->query_flags & BIT_RD)
@@ -1186,6 +1192,14 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
* differently. No queries should be sent elsewhere */
type = RESPONSE_TYPE_ANSWER;
}
if(!(iq->chase_flags&BIT_RD) && type != RESPONSE_TYPE_LAME &&
type != RESPONSE_TYPE_THROWAWAY &&
type != RESPONSE_TYPE_UNTYPED && iq->dnssec_expected) {
/* a possible answer, see if it is missing DNSSEC */
/* but not when forwarding, so we dont mark fwder lame */
if(!iter_msg_has_dnssec(iq->response))
type = RESPONSE_TYPE_LAME;
}
/* handle each of the type cases */
if(type == RESPONSE_TYPE_ANSWER) {
@@ -1225,6 +1239,10 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
delegpt_log(VERB_ALGO, iq->dp);
/* Count this as a referral. */
iq->referral_count++;
/* see if the next dp is a trust anchor, or a DS was sent
* along, indicating dnssec is expected for next zone */
iq->dnssec_expected = iter_indicates_dnssec(qstate->env,
iq->dp, iq->response);
/* stop current outstanding queries.
* FIXME: should the outstanding queries be waited for and
@@ -1264,6 +1282,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
/* Clear the query state, since this is a query restart. */
iq->deleg_msg = NULL;
iq->dp = NULL;
iq->dnssec_expected = 0;
/* Note the query restart. */
iq->query_restart_count++;
+7
View File
@@ -225,6 +225,13 @@ struct iter_qstate {
/** the number of times this query as followed a referral. */
int referral_count;
/**
* expected dnssec information for this iteration step.
* If dnssec rrsigs are expected and not given, the server is marked
* lame (dnssec-lame).
*/
int dnssec_expected;
/**
* This is flag that, if true, means that this event is
* waiting for a stub priming query.