aboutsummaryrefslogtreecommitdiff
path: root/external/unbound/validator/validator.c
diff options
context:
space:
mode:
Diffstat (limited to 'external/unbound/validator/validator.c')
-rw-r--r--external/unbound/validator/validator.c65
1 files changed, 62 insertions, 3 deletions
diff --git a/external/unbound/validator/validator.c b/external/unbound/validator/validator.c
index 9d5d5c390..a02525fee 100644
--- a/external/unbound/validator/validator.c
+++ b/external/unbound/validator/validator.c
@@ -58,8 +58,8 @@
#include "util/regional.h"
#include "util/config_file.h"
#include "util/fptr_wlist.h"
-#include "ldns/rrdef.h"
-#include "ldns/wire2str.h"
+#include "sldns/rrdef.h"
+#include "sldns/wire2str.h"
/* forward decl for cache response and normal super inform calls of a DS */
static void process_ds_response(struct module_qstate* qstate,
@@ -226,6 +226,8 @@ val_new_getmsg(struct module_qstate* qstate, struct val_qstate* vq)
sizeof(struct reply_info) - sizeof(struct rrset_ref));
if(!vq->chase_reply)
return NULL;
+ if(vq->orig_msg->rep->rrset_count > RR_COUNT_MAX)
+ return NULL; /* protect against integer overflow */
vq->chase_reply->rrsets = regional_alloc_init(qstate->region,
vq->orig_msg->rep->rrsets, sizeof(struct ub_packed_rrset_key*)
* vq->orig_msg->rep->rrset_count);
@@ -574,6 +576,61 @@ detect_wrongly_truncated(struct reply_info* rep)
return 1;
}
+/**
+ * For messages that are not referrals, if the chase reply contains an
+ * unsigned NS record in the authority section it could have been
+ * inserted by a (BIND) forwarder that thinks the zone is insecure, and
+ * that has an NS record without signatures in cache. Remove the NS
+ * record since the reply does not hinge on that record (in the authority
+ * section), but do not remove it if it removes the last record from the
+ * answer+authority sections.
+ * @param chase_reply: the chased reply, we have a key for this contents,
+ * so we should have signatures for these rrsets and not having
+ * signatures means it will be bogus.
+ * @param orig_reply: original reply, remove NS from there as well because
+ * we cannot mark the NS record as DNSSEC valid because it is not
+ * validated by signatures.
+ */
+static void
+remove_spurious_authority(struct reply_info* chase_reply,
+ struct reply_info* orig_reply)
+{
+ size_t i, found = 0;
+ int remove = 0;
+ /* if no answer and only 1 auth RRset, do not remove that one */
+ if(chase_reply->an_numrrsets == 0 && chase_reply->ns_numrrsets == 1)
+ return;
+ /* search authority section for unsigned NS records */
+ for(i = chase_reply->an_numrrsets;
+ i < chase_reply->an_numrrsets+chase_reply->ns_numrrsets; i++) {
+ struct packed_rrset_data* d = (struct packed_rrset_data*)
+ chase_reply->rrsets[i]->entry.data;
+ if(ntohs(chase_reply->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS
+ && d->rrsig_count == 0) {
+ found = i;
+ remove = 1;
+ break;
+ }
+ }
+ /* see if we found the entry */
+ if(!remove) return;
+ log_rrset_key(VERB_ALGO, "Removing spurious unsigned NS record "
+ "(likely inserted by forwarder)", chase_reply->rrsets[found]);
+
+ /* find rrset in orig_reply */
+ for(i = orig_reply->an_numrrsets;
+ i < orig_reply->an_numrrsets+orig_reply->ns_numrrsets; i++) {
+ if(ntohs(orig_reply->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS
+ && query_dname_compare(orig_reply->rrsets[i]->rk.dname,
+ chase_reply->rrsets[found]->rk.dname) == 0) {
+ /* remove from orig_msg */
+ val_reply_remove_auth(orig_reply, i);
+ break;
+ }
+ }
+ /* remove rrset from chase_reply */
+ val_reply_remove_auth(chase_reply, found);
+}
/**
* Given a "positive" response -- a response that contains an answer to the
@@ -1642,6 +1699,8 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
}
subtype = val_classify_response(qstate->query_flags, &qstate->qinfo,
&vq->qchase, vq->orig_msg->rep, vq->rrset_skip);
+ if(subtype != VAL_CLASS_REFERRAL)
+ remove_spurious_authority(vq->chase_reply, vq->orig_msg->rep);
/* check signatures in the message;
* answer and authority must be valid, additional is only checked. */
@@ -2295,7 +2354,7 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
struct key_entry_key* kkey = NULL;
enum sec_status sec = sec_status_unchecked;
char* reason = NULL;
- int downprot = 1;
+ int downprot = qstate->env->cfg->harden_algo_downgrade;
if(!dnskey_rrset) {
log_nametypeclass(VERB_OPS, "failed to prime trust anchor -- "