First step towards specific EDE DNSSEC errors

This commit is contained in:
Tom Carpay
2021-09-14 07:45:51 +00:00
parent 2360120562
commit a664e8cec4
5 changed files with 113 additions and 22 deletions
+65 -9
View File
@@ -530,6 +530,24 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
uint8_t* sigalg, char** reason, sldns_pkt_section section,
struct module_qstate* qstate)
{
return dnskeyset_verify_rrset_ede(
env, ve, rrset, dnskey, sigalg, reason, NULL, section, qstate);
}
static enum sec_status
dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
time_t now, struct ub_packed_rrset_key* rrset,
struct ub_packed_rrset_key* dnskey, size_t sig_idx,
struct rbtree_type** sortree,
char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate);
enum sec_status
dnskeyset_verify_rrset_ede(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
uint8_t* sigalg, char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate)
{
enum sec_status sec;
size_t i, num;
@@ -543,6 +561,8 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
verbose(VERB_QUERY, "rrset failed to verify due to a lack of "
"signatures");
*reason = "no signatures";
if (reason_bogus)
*reason_bogus = LDNS_EDE_RRSIGS_MISSING;
return sec_status_bogus;
}
@@ -551,12 +571,15 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
if(algo_needs_num_missing(&needs) == 0) {
verbose(VERB_QUERY, "zone has no known algorithms");
*reason = "zone has no known algorithms";
if (reason_bogus)
*reason_bogus = LDNS_EDE_UNSUPPORTED_DNSKEY_ALG;
return sec_status_insecure;
}
}
for(i=0; i<num; i++) {
sec = dnskeyset_verify_rrset_sig(env, ve, *env->now, rrset,
dnskey, i, &sortree, reason, section, qstate);
dnskey, i, &sortree, reason, reason_bogus,
section, qstate);
/* see which algorithm has been fixed up */
if(sec == sec_status_secure) {
if(!sigalg)
@@ -633,12 +656,22 @@ dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
return sec_status_bogus;
}
enum sec_status
static enum sec_status
dnskey_verify_rrset_sig_ede(struct regional* region, sldns_buffer* buf,
struct val_env* ve, time_t now,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
size_t dnskey_idx, size_t sig_idx,
struct rbtree_type** sortree, int* buf_canon,
char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate);
static enum sec_status
dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
time_t now, struct ub_packed_rrset_key* rrset,
struct ub_packed_rrset_key* dnskey, size_t sig_idx,
struct rbtree_type** sortree, char** reason, sldns_pkt_section section,
struct module_qstate* qstate)
struct rbtree_type** sortree,
char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate)
{
/* find matching keys and check them */
enum sec_status sec = sec_status_bogus;
@@ -661,9 +694,10 @@ dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
numchecked ++;
/* see if key verifies */
sec = dnskey_verify_rrset_sig(env->scratch,
sec = dnskey_verify_rrset_sig_ede(env->scratch,
env->scratch_buffer, ve, now, rrset, dnskey, i,
sig_idx, sortree, &buf_canon, reason, section, qstate);
sig_idx, sortree, &buf_canon, reason, reason_bogus,
section, qstate);
if(sec == sec_status_secure)
return sec;
}
@@ -1361,8 +1395,8 @@ subtract_1982(uint32_t a, uint32_t b)
/** check rrsig dates */
static int
check_dates(struct val_env* ve, uint32_t unow,
uint8_t* expi_p, uint8_t* incep_p, char** reason)
check_dates(struct val_env* ve, uint32_t unow, uint8_t* expi_p,
uint8_t* incep_p, char** reason, sldns_ede_code *reason_bogus)
{
/* read out the dates */
uint32_t expi, incep, now;
@@ -1386,6 +1420,7 @@ check_dates(struct val_env* ve, uint32_t unow,
sigdate_error("verify: inception after expiration, "
"signature bad", expi, incep, now);
*reason = "signature inception after expiration";
/* @TODO Tom, wat hier te doen? */
return 0;
}
if(compare_1982(incep, now) > 0) {
@@ -1397,6 +1432,8 @@ check_dates(struct val_env* ve, uint32_t unow,
sigdate_error("verify: signature bad, current time is"
" before inception date", expi, incep, now);
*reason = "signature before inception date";
if (reason_bogus)
*reason_bogus = LDNS_EDE_SIGNATURE_NOT_YET_VALID;
return 0;
}
sigdate_error("verify warning suspicious signature inception "
@@ -1410,6 +1447,8 @@ check_dates(struct val_env* ve, uint32_t unow,
sigdate_error("verify: signature expired", expi,
incep, now);
*reason = "signature expired";
if (reason_bogus)
*reason_bogus = LDNS_EDE_SIGNATURE_EXPIRED;
return 0;
}
sigdate_error("verify warning suspicious signature expiration "
@@ -1475,6 +1514,20 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
size_t dnskey_idx, size_t sig_idx,
struct rbtree_type** sortree, int* buf_canon, char** reason,
sldns_pkt_section section, struct module_qstate* qstate)
{
return dnskey_verify_rrset_sig_ede(region, buf, ve, now, rrset, dnskey,
dnskey_idx, sig_idx, sortree, buf_canon, reason, NULL,
section, qstate);
}
static enum sec_status
dnskey_verify_rrset_sig_ede(struct regional* region, sldns_buffer* buf,
struct val_env* ve, time_t now,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
size_t dnskey_idx, size_t sig_idx,
struct rbtree_type** sortree, int* buf_canon,
char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate)
{
enum sec_status sec;
uint8_t* sig; /* RRSIG rdata */
@@ -1498,6 +1551,8 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
if(!(dnskey_get_flags(dnskey, dnskey_idx) & DNSKEY_BIT_ZSK)) {
verbose(VERB_QUERY, "verify: dnskey without ZSK flag");
*reason = "dnskey without ZSK flag";
if(reason_bogus)
*reason_bogus = LDNS_EDE_NO_ZONE_KEY_BIT_SET;
return sec_status_bogus;
}
@@ -1598,7 +1653,8 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
/* verify inception, expiration dates
* Do this last so that if you ignore expired-sigs the
* rest is sure to be OK. */
if(!check_dates(ve, now, sig+2+8, sig+2+12, reason)) {
if(!check_dates(ve, now, sig+2+8, sig+2+12,
reason, reason_bogus)) {
return sec_status_bogus;
}
}
+9
View File
@@ -45,6 +45,7 @@
#define VALIDATOR_VAL_SIGCRYPT_H
#include "util/data/packed_rrset.h"
#include "sldns/pkthdr.h"
#include "sldns/rrdef.h"
struct val_env;
struct module_env;
struct module_qstate;
@@ -266,6 +267,12 @@ enum sec_status dnskeyset_verify_rrset(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* rrset,
struct ub_packed_rrset_key* dnskey, uint8_t* sigalg, char** reason,
sldns_pkt_section section, struct module_qstate* qstate);
enum sec_status dnskeyset_verify_rrset_ede(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* rrset,
struct ub_packed_rrset_key* dnskey, uint8_t* sigalg,
char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate);
/**
* verify rrset against one specific dnskey (from rrset)
@@ -285,6 +292,7 @@ enum sec_status dnskey_verify_rrset(struct module_env* env,
struct ub_packed_rrset_key* dnskey, size_t dnskey_idx, char** reason,
sldns_pkt_section section, struct module_qstate* qstate);
#if 0
/**
* verify rrset, with dnskey rrset, for a specific rrsig in rrset
* @param env: module environment, scratch space is used.
@@ -306,6 +314,7 @@ enum sec_status dnskeyset_verify_rrset_sig(struct module_env* env,
struct ub_packed_rrset_key* dnskey, size_t sig_idx,
struct rbtree_type** sortree, char** reason, sldns_pkt_section section,
struct module_qstate* qstate);
#endif
/**
* verify rrset, with specific dnskey(from set), for a specific rrsig
+16 -6
View File
@@ -332,11 +332,11 @@ rrset_get_ttl(struct ub_packed_rrset_key* rrset)
return d->ttl;
}
enum sec_status
static enum sec_status
val_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys,
uint8_t* sigalg, char** reason, sldns_pkt_section section,
struct module_qstate* qstate)
uint8_t* sigalg, char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate)
{
enum sec_status sec;
struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
@@ -358,8 +358,8 @@ val_verify_rrset(struct module_env* env, struct val_env* ve,
}
log_nametypeclass(VERB_ALGO, "verify rrset", rrset->rk.dname,
ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class));
sec = dnskeyset_verify_rrset(env, ve, rrset, keys, sigalg, reason,
section, qstate);
sec = dnskeyset_verify_rrset_ede(env, ve, rrset, keys, sigalg, reason,
reason_bogus, section, qstate);
verbose(VERB_ALGO, "verify result: %s", sec_status_to_string(sec));
regional_free_all(env->scratch);
@@ -393,6 +393,16 @@ enum sec_status
val_verify_rrset_entry(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct key_entry_key* kkey,
char** reason, sldns_pkt_section section, struct module_qstate* qstate)
{
return val_verify_rrset_entry_ede(
env, ve, rrset, kkey, reason, NULL, section, qstate);
}
enum sec_status
val_verify_rrset_entry_ede(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct key_entry_key* kkey,
char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate)
{
/* temporary dnskey rrset-key */
struct ub_packed_rrset_key dnskey;
@@ -406,7 +416,7 @@ val_verify_rrset_entry(struct module_env* env, struct val_env* ve,
dnskey.entry.key = &dnskey;
dnskey.entry.data = kd->rrset_data;
sec = val_verify_rrset(env, ve, rrset, &dnskey, kd->algo, reason,
section, qstate);
reason_bogus, section, qstate);
return sec;
}
+9
View File
@@ -43,6 +43,7 @@
#define VALIDATOR_VAL_UTILS_H
#include "util/data/packed_rrset.h"
#include "sldns/pkthdr.h"
#include "sldns/rrdef.h"
struct query_info;
struct reply_info;
struct val_env;
@@ -113,6 +114,7 @@ void val_find_signer(enum val_classification subtype,
struct query_info* qinf, struct reply_info* rep,
size_t cname_skip, uint8_t** signer_name, size_t* signer_len);
#if 0
/**
* Verify RRset with keys
* @param env: module environment (scratch buffer)
@@ -130,6 +132,7 @@ enum sec_status val_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys,
uint8_t* sigalg, char** reason, sldns_pkt_section section,
struct module_qstate* qstate);
#endif
/**
* Verify RRset with keys from a keyset.
@@ -147,6 +150,12 @@ enum sec_status val_verify_rrset_entry(struct module_env* env,
struct key_entry_key* kkey, char** reason, sldns_pkt_section section,
struct module_qstate* qstate);
enum sec_status val_verify_rrset_entry_ede(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* rrset,
struct key_entry_key* kkey, char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate);
/**
* Verify DNSKEYs with DS rrset. Like val_verify_new_DNSKEYs but
* returns a sec_status instead of a key_entry.
+14 -7
View File
@@ -592,6 +592,7 @@ validate_msg_signatures(struct module_qstate* qstate, struct module_env* env,
enum sec_status sec;
int dname_seen = 0;
char* reason = NULL;
sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
/* validate the ANSWER section */
for(i=0; i<chase_reply->an_numrrsets; i++) {
@@ -612,8 +613,8 @@ validate_msg_signatures(struct module_qstate* qstate, struct module_env* env,
}
/* Verify the answer rrset */
sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason,
LDNS_SECTION_ANSWER, qstate);
sec = val_verify_rrset_entry_ede(env, ve, s, key_entry, &reason,
&reason_bogus, LDNS_SECTION_ANSWER, qstate);
/* If the (answer) rrset failed to validate, then this
* message is BAD. */
if(sec != sec_status_secure) {
@@ -627,6 +628,7 @@ validate_msg_signatures(struct module_qstate* qstate, struct module_env* env,
errinf(qstate, "for DNAME");
errinf_origin(qstate, qstate->reply_origin);
chase_reply->security = sec_status_bogus;
chase_reply->reason_bogus = reason_bogus;
return 0;
}
@@ -642,8 +644,8 @@ validate_msg_signatures(struct module_qstate* qstate, struct module_env* env,
for(i=chase_reply->an_numrrsets; i<chase_reply->an_numrrsets+
chase_reply->ns_numrrsets; i++) {
s = chase_reply->rrsets[i];
sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason,
LDNS_SECTION_AUTHORITY, qstate);
sec = val_verify_rrset_entry_ede(env, ve, s, key_entry, &reason,
&reason_bogus, LDNS_SECTION_AUTHORITY, qstate);
/* If anything in the authority section fails to be secure,
* we have a bad message. */
if(sec != sec_status_secure) {
@@ -654,6 +656,7 @@ validate_msg_signatures(struct module_qstate* qstate, struct module_env* env,
errinf_origin(qstate, qstate->reply_origin);
errinf_rrset(qstate, s);
chase_reply->security = sec_status_bogus;
chase_reply->reason_bogus = reason_bogus;
return 0;
}
}
@@ -2001,17 +2004,21 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
vq->orig_msg->rep, vq->rrset_skip);
/* store overall validation result in orig_msg */
if(vq->rrset_skip == 0)
if(vq->rrset_skip == 0) {
vq->orig_msg->rep->security = vq->chase_reply->security;
else if(subtype != VAL_CLASS_REFERRAL ||
vq->orig_msg->rep->reason_bogus = vq->chase_reply->reason_bogus;
} else if(subtype != VAL_CLASS_REFERRAL ||
vq->rrset_skip < vq->orig_msg->rep->an_numrrsets +
vq->orig_msg->rep->ns_numrrsets) {
/* ignore sec status of additional section if a referral
* type message skips there and
* use the lowest security status as end result. */
if(vq->chase_reply->security < vq->orig_msg->rep->security)
if(vq->chase_reply->security < vq->orig_msg->rep->security) {
vq->orig_msg->rep->security =
vq->chase_reply->security;
vq->orig_msg->rep->reason_bogus =
vq->chase_reply->reason_bogus;
}
}
if(subtype == VAL_CLASS_REFERRAL) {