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;
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;
}
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)
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;
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;
}
/** 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;
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) {
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 "
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 "
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 */
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;
}
/* 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;
}
}
#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;
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)
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.
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
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->
}
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);
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;
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;
}
#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;
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)
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.
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.
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++) {
}
/* 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) {
errinf(qstate, "for DNAME");
errinf_origin(qstate, qstate->reply_origin);
chase_reply->security = sec_status_bogus;
+ chase_reply->reason_bogus = reason_bogus;
return 0;
}
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) {
errinf_origin(qstate, qstate->reply_origin);
errinf_rrset(qstate, s);
chase_reply->security = sec_status_bogus;
+ chase_reply->reason_bogus = reason_bogus;
return 0;
}
}
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) {