mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
autotrust work
git-svn-id: file:///svn/unbound/trunk@1760 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
a85b563d37
commit
21e791248f
11 changed files with 419 additions and 120 deletions
|
|
@ -1,3 +1,6 @@
|
|||
13 August 2009: Wouter
|
||||
- autotrust read anchor files. locked trust anchors.
|
||||
|
||||
12 August 2009: Wouter
|
||||
- autotrust import work.
|
||||
|
||||
|
|
|
|||
|
|
@ -476,13 +476,16 @@ int
|
|||
iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
|
||||
struct dns_msg* msg, uint16_t dclass)
|
||||
{
|
||||
struct trust_anchor* a;
|
||||
/* information not available, !env->anchors can be common */
|
||||
if(!env || !env->anchors || !dp || !dp->name)
|
||||
return 0;
|
||||
/* a trust anchor exists with this name, RRSIGs expected */
|
||||
if(anchor_find(env->anchors, dp->name, dp->namelabs, dp->namelen,
|
||||
dclass))
|
||||
if((a=anchor_find(env->anchors, dp->name, dp->namelabs, dp->namelen,
|
||||
dclass))) {
|
||||
lock_basic_unlock(&a->lock);
|
||||
return 1;
|
||||
}
|
||||
/* see if DS rrset was given, in AUTH section */
|
||||
if(msg && msg->rep &&
|
||||
reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen,
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ static void lock_error(struct checked_lock* lock,
|
|||
(lock->type==check_lock_rwlock)?"rwlock": "badtype")), err);
|
||||
log_err("complete status display:");
|
||||
total_debug_info();
|
||||
abort();
|
||||
fatal_exit("bailing out");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ test_anchor_empty(struct val_anchors* a)
|
|||
static void
|
||||
test_anchor_one(ldns_buffer* buff, struct val_anchors* a)
|
||||
{
|
||||
struct trust_anchor* ta;
|
||||
uint16_t c = LDNS_RR_CLASS_IN;
|
||||
unit_assert(anchor_store_str(a, buff,
|
||||
"nl. DS 42860 5 1 14D739EB566D2B1A5E216A0BA4D17FA9B038BE4A"));
|
||||
|
|
@ -71,11 +72,19 @@ test_anchor_one(ldns_buffer* buff, struct val_anchors* a)
|
|||
unit_assert(anchors_lookup(a, (uint8_t*)"\003com\000", 5, c) == NULL);
|
||||
unit_assert(anchors_lookup(a,
|
||||
(uint8_t*)"\007example\003com\000", 11, c) == NULL);
|
||||
unit_assert(anchors_lookup(a, (uint8_t*)"\002nl\000", 4, c) != NULL);
|
||||
unit_assert(anchors_lookup(a,
|
||||
(uint8_t*)"\004labs\002nl\000", 9, c) != NULL);
|
||||
unit_assert(anchors_lookup(a,
|
||||
(uint8_t*)"\004fabs\002nl\000", 9, c) != NULL);
|
||||
|
||||
unit_assert((ta=anchors_lookup(a,
|
||||
(uint8_t*)"\002nl\000", 4, c)) != NULL);
|
||||
lock_basic_unlock(&ta->lock);
|
||||
|
||||
unit_assert((ta=anchors_lookup(a,
|
||||
(uint8_t*)"\004labs\002nl\000", 9, c)) != NULL);
|
||||
lock_basic_unlock(&ta->lock);
|
||||
|
||||
unit_assert((ta=anchors_lookup(a,
|
||||
(uint8_t*)"\004fabs\002nl\000", 9, c)) != NULL);
|
||||
lock_basic_unlock(&ta->lock);
|
||||
|
||||
unit_assert(anchors_lookup(a, (uint8_t*)"\002oo\000", 4, c) == NULL);
|
||||
}
|
||||
|
||||
|
|
@ -91,16 +100,23 @@ test_anchors(ldns_buffer* buff, struct val_anchors* a)
|
|||
unit_assert(anchors_lookup(a, (uint8_t*)"\003com\000", 5, c) == NULL);
|
||||
unit_assert(anchors_lookup(a,
|
||||
(uint8_t*)"\007example\003com\000", 11, c) == NULL);
|
||||
|
||||
unit_assert(ta = anchors_lookup(a, (uint8_t*)"\002nl\000", 4, c));
|
||||
unit_assert(query_dname_compare(ta->name, (uint8_t*)"\002nl\000")==0);
|
||||
lock_basic_unlock(&ta->lock);
|
||||
|
||||
unit_assert(ta = anchors_lookup(a,
|
||||
(uint8_t*)"\004labs\002nl\000", 9, c));
|
||||
unit_assert(query_dname_compare(ta->name,
|
||||
(uint8_t*)"\004labs\002nl\000") == 0);
|
||||
lock_basic_unlock(&ta->lock);
|
||||
|
||||
unit_assert(ta = anchors_lookup(a,
|
||||
(uint8_t*)"\004fabs\002nl\000", 9, c));
|
||||
unit_assert(query_dname_compare(ta->name,
|
||||
(uint8_t*)"\002nl\000") == 0);
|
||||
lock_basic_unlock(&ta->lock);
|
||||
|
||||
unit_assert(anchors_lookup(a, (uint8_t*)"\002oo\000", 4, c) == NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,12 +41,11 @@
|
|||
#include "config.h"
|
||||
#include "validator/autotrust.h"
|
||||
#include "validator/val_anchor.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/log.h"
|
||||
#include "util/module.h"
|
||||
#include "util/net_help.h"
|
||||
|
||||
/** max length of parse lines */
|
||||
#define MAXLEN 10240
|
||||
|
||||
struct autr_global_data* autr_global_create(void)
|
||||
{
|
||||
struct autr_global_data* global;
|
||||
|
|
@ -104,31 +103,31 @@ position_in_string(char *str, const char* sub)
|
|||
}
|
||||
if (pos < 0)
|
||||
return pos;
|
||||
return pos + strlen(sub);
|
||||
return pos + (int)strlen(sub);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse comments
|
||||
* @param str: to parse
|
||||
* @param ta: trust key autotrust metadata
|
||||
* @param tp: trust anchor
|
||||
* @return false on failure.
|
||||
*/
|
||||
static int
|
||||
parse_comments(char* str, struct autr_ta_data* ta, struct trust_anchor* tp)
|
||||
parse_comments(char* str, struct autr_ta* ta)
|
||||
{
|
||||
char* comment = (char*) malloc(sizeof(char)*MAXLEN);
|
||||
int len = (int)strlen(str), pos = 0, timestamp = 0;
|
||||
char* comment = (char*) malloc(sizeof(char)*len+1);
|
||||
char* comments = comment;
|
||||
int len = strlen(str), pos = 0, timestamp = 0;
|
||||
if (len >= MAXLEN) {
|
||||
log_err("line too long");
|
||||
if(!comment) {
|
||||
log_err("malloc failure in parse");
|
||||
return 0;
|
||||
}
|
||||
/* skip over whitespace and data at start of line */
|
||||
while (*str != '\0' && *str != ';')
|
||||
str++;
|
||||
/* comments */
|
||||
if (*str == ';')
|
||||
str++;
|
||||
/* copy comments */
|
||||
while (*str != '\0')
|
||||
{
|
||||
*comments = *str;
|
||||
|
|
@ -139,10 +138,6 @@ parse_comments(char* str, struct autr_ta_data* ta, struct trust_anchor* tp)
|
|||
|
||||
comments = comment;
|
||||
|
||||
if (!ta || !comments) {
|
||||
log_err("malloc failure in parse");
|
||||
return 0;
|
||||
}
|
||||
/* read state */
|
||||
pos = position_in_string(comments, "state=");
|
||||
if (pos >= (int) strlen(comments))
|
||||
|
|
@ -152,10 +147,11 @@ parse_comments(char* str, struct autr_ta_data* ta, struct trust_anchor* tp)
|
|||
return 0;
|
||||
}
|
||||
if (pos <= 0)
|
||||
ta->s = AUTR_STATE_START;
|
||||
ta->s = AUTR_STATE_VALID;
|
||||
else
|
||||
{
|
||||
int s = (int) comments[pos] - '0';
|
||||
char* str = ldns_rdf2str(ldns_rr_owner(ta->rr));
|
||||
|
||||
switch(s)
|
||||
{
|
||||
|
|
@ -168,10 +164,9 @@ parse_comments(char* str, struct autr_ta_data* ta, struct trust_anchor* tp)
|
|||
ta->s = s;
|
||||
break;
|
||||
default:
|
||||
log_nametypeclass(0, "warning: trust anchor "
|
||||
"has undefined state, considered "
|
||||
"NewKey", tp->name,
|
||||
LDNS_RR_TYPE_DNSKEY, tp->dclass);
|
||||
log_warn("trust anchor [%s, DNSKEY, id=%i] has "
|
||||
"undefined state, considered NewKey",
|
||||
str, ldns_calc_keytag(ta->rr));
|
||||
ta->s = AUTR_STATE_START;
|
||||
break;
|
||||
}
|
||||
|
|
@ -191,7 +186,7 @@ parse_comments(char* str, struct autr_ta_data* ta, struct trust_anchor* tp)
|
|||
else
|
||||
{
|
||||
comments += pos;
|
||||
ta->pending_count = atoi(comments);
|
||||
ta->pending_count = (uint8_t)atoi(comments);
|
||||
}
|
||||
|
||||
/* read last change */
|
||||
|
|
@ -209,12 +204,17 @@ parse_comments(char* str, struct autr_ta_data* ta, struct trust_anchor* tp)
|
|||
}
|
||||
if (pos < 0 || !timestamp)
|
||||
{
|
||||
log_warn("trust anchor has no timestamp, considered NOW");
|
||||
/* Should we warn about this? It happens for key priming.
|
||||
ldns_rdf* owner = ldns_rr_owner(ta->rr);
|
||||
char* str = ldns_rdf2str(owner);
|
||||
log_warn("trust anchor [%s, DNSKEY, id=%i] has no timestamp, "
|
||||
"considered NOW", str, ldns_calc_keytag(ta->rr));
|
||||
free(str);
|
||||
ta->last_change = time(NULL);
|
||||
*/
|
||||
ta->last_change = (uint32_t)time(NULL);
|
||||
}
|
||||
else
|
||||
ta->last_change = timestamp;
|
||||
ta->last_change = (uint32_t)timestamp;
|
||||
|
||||
free(comment);
|
||||
return 1;
|
||||
|
|
@ -236,80 +236,191 @@ str_contains_data(char* str, char comment)
|
|||
|
||||
/** Get DNSKEY flags */
|
||||
static int
|
||||
ta_dnskey_flags(struct ta_key* ta)
|
||||
dnskey_flags(ldns_rr* rr)
|
||||
{
|
||||
uint16_t f;
|
||||
if(ta->type != LDNS_RR_TYPE_DNSKEY)
|
||||
if(ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY)
|
||||
return 0;
|
||||
if(ta->len < 2+2)
|
||||
return 0;
|
||||
memmove(&f, ta->data+2, 2);
|
||||
f = ntohs(f);
|
||||
return f;
|
||||
return (int)ldns_read_uint16(ldns_rdf_data(ldns_rr_dnskey_flags(rr)));
|
||||
}
|
||||
|
||||
|
||||
/** Check if KSK DNSKEY */
|
||||
static int
|
||||
rr_is_dnskey_sep(struct ta_key* ta)
|
||||
rr_is_dnskey_sep(ldns_rr* rr)
|
||||
{
|
||||
return (ta_dnskey_flags(ta)&DNSKEY_BIT_SEP);
|
||||
return (dnskey_flags(rr)&DNSKEY_BIT_SEP);
|
||||
}
|
||||
|
||||
/** create ta */
|
||||
static struct autr_ta*
|
||||
autr_ta_create(ldns_rr* rr)
|
||||
{
|
||||
struct autr_ta* ta = (struct autr_ta*)calloc(1, sizeof(*ta));
|
||||
if(!ta) {
|
||||
ldns_rr_free(rr);
|
||||
return NULL;
|
||||
}
|
||||
ta->rr = rr;
|
||||
return ta;
|
||||
}
|
||||
|
||||
/** create tp */
|
||||
static struct trust_anchor*
|
||||
autr_tp_create(struct val_anchors* anchors, ldns_rr* rr)
|
||||
{
|
||||
ldns_rdf* own = ldns_rr_owner(rr);
|
||||
struct trust_anchor* tp = (struct trust_anchor*)calloc(1, sizeof(*tp));
|
||||
if(!tp) return NULL;
|
||||
tp->name = memdup(ldns_rdf_data(own), ldns_rdf_size(own));
|
||||
if(!tp->name) {
|
||||
free(tp);
|
||||
return NULL;
|
||||
}
|
||||
tp->namelen = ldns_rdf_size(own);
|
||||
tp->namelabs = dname_count_labels(tp->name);
|
||||
tp->node.key = tp;
|
||||
tp->dclass = ldns_rr_get_class(rr);
|
||||
tp->autr = (struct autr_point_data*)calloc(1, sizeof(*tp->autr));
|
||||
if(!tp->autr) {
|
||||
free(tp->name);
|
||||
free(tp);
|
||||
return NULL;
|
||||
}
|
||||
tp->autr->pnode.key = tp;
|
||||
|
||||
lock_basic_lock(&anchors->lock);
|
||||
(void)rbtree_insert(anchors->tree, &tp->node);
|
||||
lock_basic_unlock(&anchors->lock);
|
||||
lock_basic_init(&tp->lock);
|
||||
lock_protect(&tp->lock, tp, sizeof(*tp));
|
||||
lock_protect(&tp->lock, tp->autr, sizeof(*tp->autr));
|
||||
return tp;
|
||||
}
|
||||
|
||||
void autr_point_delete(struct trust_anchor* tp)
|
||||
{
|
||||
if(!tp)
|
||||
return;
|
||||
lock_unprotect(&tp->lock, tp);
|
||||
lock_unprotect(&tp->lock, tp->autr);
|
||||
lock_basic_destroy(&tp->lock);
|
||||
free(tp->autr);
|
||||
free(tp->name);
|
||||
free(tp);
|
||||
}
|
||||
|
||||
/** find or add a new trust point for autotrust */
|
||||
static struct trust_anchor*
|
||||
find_add_tp(struct val_anchors* anchors, ldns_rr* rr)
|
||||
{
|
||||
struct trust_anchor* tp;
|
||||
ldns_rdf* own = ldns_rr_owner(rr);
|
||||
tp = anchor_find(anchors, ldns_rdf_data(own),
|
||||
dname_count_labels(ldns_rdf_data(own)),
|
||||
ldns_rdf_size(own), ldns_rr_get_class(rr));
|
||||
if(tp) {
|
||||
if(!tp->autr) {
|
||||
log_err("anchor cannot be with and without autotrust");
|
||||
lock_basic_unlock(&tp->lock);
|
||||
return NULL;
|
||||
}
|
||||
return tp;
|
||||
}
|
||||
tp = autr_tp_create(anchors, rr);
|
||||
lock_basic_lock(&tp->lock);
|
||||
return tp;
|
||||
}
|
||||
|
||||
/** Add trust anchor from RR. */
|
||||
static struct autr_ta*
|
||||
add_trustanchor_frm_rr(struct val_anchors* anchors, ldns_rr* rr,
|
||||
struct trust_anchor** tp)
|
||||
{
|
||||
struct autr_ta* ta = autr_ta_create(rr);
|
||||
if(!ta)
|
||||
return NULL;
|
||||
*tp = find_add_tp(anchors, rr);
|
||||
/* add ta to tp */
|
||||
ta->next = (*tp)->autr->keys;
|
||||
(*tp)->autr->keys = ta;
|
||||
lock_basic_unlock(&(*tp)->lock);
|
||||
return ta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new trust anchor from a string in file.
|
||||
* @param anchors: all anchors
|
||||
* @param str: string with comments before the anchor, if any comments.
|
||||
* @param str: string with anchor and comments, if any comments.
|
||||
* @param tp: trust point returned.
|
||||
* @return new key in trust point.
|
||||
*/
|
||||
static struct ta_key*
|
||||
static struct autr_ta*
|
||||
add_trustanchor_frm_str(struct val_anchors* anchors, char* str,
|
||||
struct trust_anchor** tp)
|
||||
{
|
||||
if(!str_contains_data(str, ';'))
|
||||
ldns_rr* rr;
|
||||
struct autr_ta* ta = NULL;
|
||||
ldns_status lstatus;
|
||||
if (!str_contains_data(str, ';'))
|
||||
return NULL; /* empty line */
|
||||
if (LDNS_STATUS_OK !=
|
||||
(lstatus = ldns_rr_new_frm_str(&rr, str, 0, NULL, NULL)))
|
||||
{
|
||||
log_err("ldns error while converting string to RR: %s",
|
||||
ldns_get_errorstr_by_id(lstatus));
|
||||
return NULL;
|
||||
}
|
||||
ta = add_trustanchor_frm_rr(anchors, rr, tp);
|
||||
return ta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load single anchor
|
||||
* @param anchors: all points.
|
||||
* @param str: comments line
|
||||
* @param fname: filename
|
||||
* @return false on failure.
|
||||
*/
|
||||
static int
|
||||
load_trustanchor(struct val_anchors* anchors, char* str)
|
||||
load_trustanchor(struct val_anchors* anchors, char* str, const char* fname)
|
||||
{
|
||||
int status_ok = 1;
|
||||
struct ta_key* ta = NULL;
|
||||
struct autr_ta* ta = NULL;
|
||||
struct trust_anchor* tp = NULL;
|
||||
|
||||
if (!str_contains_data(str, ';'))
|
||||
return status_ok; /* empty lines allowed */
|
||||
ta = add_trustanchor_frm_str(anchors, str, &tp);
|
||||
if (ta) {
|
||||
status_ok = parse_comments(str, ta->autr, tp);
|
||||
if (rr_is_dnskey_sep(ta)) {
|
||||
if (ta->autr->s == AUTR_STATE_VALID)
|
||||
if(!ta)
|
||||
return 0;
|
||||
lock_basic_lock(&tp->lock);
|
||||
if(!parse_comments(str, ta)) {
|
||||
lock_basic_unlock(&tp->lock);
|
||||
return 0;
|
||||
}
|
||||
if (rr_is_dnskey_sep(ta->rr)) {
|
||||
if (ta->s == AUTR_STATE_VALID)
|
||||
tp->autr->valid ++;
|
||||
else if (ta->autr->s == AUTR_STATE_MISSING)
|
||||
else if (ta->s == AUTR_STATE_MISSING)
|
||||
tp->autr->missing ++;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(!tp->autr->file) {
|
||||
/* TODO insert tp into probe tree */
|
||||
tp->autr->file = strdup(fname);
|
||||
if(!tp->autr->file) {
|
||||
lock_basic_unlock(&tp->lock);
|
||||
return 0;
|
||||
return status_ok;
|
||||
}
|
||||
}
|
||||
lock_basic_unlock(&tp->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int autr_read_file(struct val_anchors* anchors, ldns_buffer* parsebuf,
|
||||
const char* nm)
|
||||
int autr_read_file(struct val_anchors* anchors, const char* nm)
|
||||
{
|
||||
/* the file descriptor */
|
||||
FILE* fd;
|
||||
/* keep track of line numbers */
|
||||
int line_nr = 0;
|
||||
/* single line */
|
||||
char line[MAXLEN];
|
||||
char line[10240];
|
||||
|
||||
if (!(fd = fopen(nm, "r"))) {
|
||||
log_err("unable to open %s for reading: %s",
|
||||
|
|
@ -317,9 +428,13 @@ int autr_read_file(struct val_anchors* anchors, ldns_buffer* parsebuf,
|
|||
return 0;
|
||||
}
|
||||
verbose(VERB_ALGO, "reading trust anchor file %s", nm);
|
||||
while (fgets(line, MAXLEN, fd) != NULL) {
|
||||
/* TODO: read line to see if special marker for revoked tp */
|
||||
/* TODO: read next probe time (if in file, otherwise now+0-100s) */
|
||||
while (fgets(line, (int)sizeof(line), fd) != NULL) {
|
||||
line_nr++;
|
||||
if (!load_trustanchor(anchors, line)) {
|
||||
if (!str_contains_data(line, ';'))
|
||||
continue; /* empty lines allowed */
|
||||
if (!load_trustanchor(anchors, line, nm)) {
|
||||
log_err("failed to load trust anchor from %s "
|
||||
"at line %i, skipping", nm, line_nr);
|
||||
/* try to do the rest */
|
||||
|
|
@ -330,3 +445,19 @@ int autr_read_file(struct val_anchors* anchors, ldns_buffer* parsebuf,
|
|||
return 1;
|
||||
}
|
||||
|
||||
void autr_write_file(struct trust_anchor* tp)
|
||||
{
|
||||
/* write pretty header */
|
||||
/* write revoked tp special marker */
|
||||
/* write next probe time */
|
||||
/* write anchors */
|
||||
}
|
||||
|
||||
int autr_process_prime(struct module_env* env, struct val_env* ve,
|
||||
struct trust_anchor* tp, struct ub_packed_rrset_key* dnskey_rrset)
|
||||
{
|
||||
struct val_anchors* anchors = env->anchors;
|
||||
/* autotrust update trust anchors */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,10 @@
|
|||
#define VALIDATOR_AUTOTRUST_H
|
||||
#include "util/rbtree.h"
|
||||
struct val_anchors;
|
||||
struct trust_anchor;
|
||||
struct ub_packed_rrset_key;
|
||||
struct module_env;
|
||||
struct val_env;
|
||||
|
||||
/** Autotrust anchor states */
|
||||
typedef enum {
|
||||
|
|
@ -57,7 +61,11 @@ typedef enum {
|
|||
/**
|
||||
* Autotrust metadata for one trust anchor key.
|
||||
*/
|
||||
struct autr_ta_data {
|
||||
struct autr_ta {
|
||||
/** next key */
|
||||
struct autr_ta* next;
|
||||
/** the RR */
|
||||
ldns_rr* rr;
|
||||
/** 5011 state */
|
||||
autr_state_t s;
|
||||
/** last update of key */
|
||||
|
|
@ -78,7 +86,7 @@ struct autr_point_data {
|
|||
const char* file;
|
||||
/** next probe time */
|
||||
uint32_t next_probe_time;
|
||||
/** rbtree node for probe sort */
|
||||
/** rbtree node for probe sort, key is struct trust_anchor */
|
||||
rbnode_t pnode;
|
||||
|
||||
/** last queried DNSKEY set */
|
||||
|
|
@ -94,6 +102,8 @@ struct autr_point_data {
|
|||
uint8_t valid;
|
||||
/** number of missing DNSKEYs */
|
||||
uint8_t missing;
|
||||
/** the keys */
|
||||
struct autr_ta* keys;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -122,11 +132,35 @@ int probetree_cmp(const void* x, const void* y);
|
|||
/**
|
||||
* Read autotrust file.
|
||||
* @param anchors: the anchors structure.
|
||||
* @param parsebuf: buffer temporary for parsing data.
|
||||
* @param nm: name of the file (copied).
|
||||
* @return false on failure.
|
||||
*/
|
||||
int autr_read_file(struct val_anchors* anchors, ldns_buffer* parsebuf,
|
||||
const char* nm);
|
||||
int autr_read_file(struct val_anchors* anchors, const char* nm);
|
||||
|
||||
/**
|
||||
* Write autotrust file.
|
||||
* @param tp: trust point to write.
|
||||
*/
|
||||
void autr_write_file(struct trust_anchor* tp);
|
||||
|
||||
/**
|
||||
* Delete autr anchor, deletes the autr data but does not do
|
||||
* unlinking from trees, caller does that.
|
||||
* @param tp: trust point to delete.
|
||||
*/
|
||||
void autr_point_delete(struct trust_anchor* tp);
|
||||
|
||||
/**
|
||||
* Perform autotrust processing.
|
||||
* @param env: qstate environment with the anchors structure.
|
||||
* @param ve: validator environment for verification of rrsigs.
|
||||
* @param tp: trust anchor to process.
|
||||
* @param dnskey_rrset: DNSKEY rrset probed (can be NULL if bad prime result).
|
||||
* allocated in a region. Has not been validated yet.
|
||||
* @return false if trust anchor was revoked completely.
|
||||
* Otherwise logs errors to log, does not change return value.
|
||||
*/
|
||||
int autr_process_prime(struct module_env* env, struct val_env* ve,
|
||||
struct trust_anchor* tp, struct ub_packed_rrset_key* dnskey_rrset);
|
||||
|
||||
#endif /* VALIDATOR_AUTOTRUST_H */
|
||||
|
|
|
|||
|
|
@ -89,14 +89,31 @@ anchors_create()
|
|||
anchors_delete(a);
|
||||
return NULL;
|
||||
}
|
||||
lock_basic_init(&a->lock);
|
||||
lock_protect(&a->lock, a, sizeof(*a));
|
||||
return a;
|
||||
}
|
||||
|
||||
/** destroy locks in tree and delete autotrust anchors */
|
||||
static void
|
||||
anchors_delfunc(rbnode_t* elem, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct trust_anchor* ta = (struct trust_anchor*)elem;
|
||||
if(ta->autr) {
|
||||
autr_point_delete(ta);
|
||||
} else {
|
||||
lock_basic_destroy(&ta->lock);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
anchors_delete(struct val_anchors* anchors)
|
||||
{
|
||||
if(!anchors)
|
||||
return;
|
||||
lock_unprotect(&anchors->lock, anchors);
|
||||
lock_basic_destroy(&anchors->lock);
|
||||
traverse_postorder(anchors->tree, anchors_delfunc, NULL);
|
||||
free(anchors->tree);
|
||||
regional_destroy(anchors->region);
|
||||
autr_global_delete(anchors->autr);
|
||||
|
|
@ -109,10 +126,13 @@ init_parents(struct val_anchors* anchors)
|
|||
{
|
||||
struct trust_anchor* node, *prev = NULL, *p;
|
||||
int m;
|
||||
lock_basic_lock(&anchors->lock);
|
||||
RBTREE_FOR(node, struct trust_anchor*, anchors->tree) {
|
||||
lock_basic_lock(&node->lock);
|
||||
node->parent = NULL;
|
||||
if(!prev || prev->dclass != node->dclass) {
|
||||
prev = node;
|
||||
lock_basic_unlock(&node->lock);
|
||||
continue;
|
||||
}
|
||||
(void)dname_lab_cmp(prev->name, prev->namelabs, node->name,
|
||||
|
|
@ -128,8 +148,10 @@ init_parents(struct val_anchors* anchors)
|
|||
node->parent = p;
|
||||
break;
|
||||
}
|
||||
lock_basic_unlock(&node->lock);
|
||||
prev = node;
|
||||
}
|
||||
lock_basic_unlock(&anchors->lock);
|
||||
}
|
||||
|
||||
struct trust_anchor*
|
||||
|
|
@ -138,12 +160,18 @@ anchor_find(struct val_anchors* anchors, uint8_t* name, int namelabs,
|
|||
{
|
||||
struct trust_anchor key;
|
||||
rbnode_t* n;
|
||||
if(!name) return NULL;
|
||||
key.node.key = &key;
|
||||
key.name = name;
|
||||
key.namelabs = namelabs;
|
||||
key.namelen = namelen;
|
||||
key.dclass = dclass;
|
||||
lock_basic_lock(&anchors->lock);
|
||||
n = rbtree_search(anchors->tree, &key);
|
||||
if(n) {
|
||||
lock_basic_lock(&((struct trust_anchor*)n->key)->lock);
|
||||
}
|
||||
lock_basic_unlock(&anchors->lock);
|
||||
if(!n)
|
||||
return NULL;
|
||||
return (struct trust_anchor*)n->key;
|
||||
|
|
@ -167,7 +195,10 @@ anchor_new_ta(struct val_anchors* anchors, uint8_t* name, int namelabs,
|
|||
ta->namelabs = namelabs;
|
||||
ta->namelen = namelen;
|
||||
ta->dclass = dclass;
|
||||
lock_basic_init(&ta->lock);
|
||||
lock_basic_lock(&anchors->lock);
|
||||
r = rbtree_insert(anchors->tree, &ta->node);
|
||||
lock_basic_unlock(&anchors->lock);
|
||||
log_assert(r != NULL);
|
||||
return ta;
|
||||
}
|
||||
|
|
@ -236,22 +267,29 @@ anchor_store_new_key(struct val_anchors* anchors, uint8_t* name, uint16_t type,
|
|||
ta = anchor_new_ta(anchors, name, namelabs, namelen, dclass);
|
||||
if(!ta)
|
||||
return NULL;
|
||||
lock_basic_lock(&ta->lock);
|
||||
}
|
||||
if(!rdata)
|
||||
if(!rdata) {
|
||||
lock_basic_unlock(&ta->lock);
|
||||
return ta;
|
||||
}
|
||||
/* look for duplicates */
|
||||
if(anchor_find_key(ta, rdata, rdata_len, type)) {
|
||||
lock_basic_unlock(&ta->lock);
|
||||
return ta;
|
||||
}
|
||||
k = anchor_new_ta_key(anchors, rdata, rdata_len, type);
|
||||
if(!k)
|
||||
if(!k) {
|
||||
lock_basic_unlock(&ta->lock);
|
||||
return NULL;
|
||||
}
|
||||
/* add new key */
|
||||
if(type == LDNS_RR_TYPE_DS)
|
||||
ta->numDS++;
|
||||
else ta->numDNSKEY++;
|
||||
k->next = ta->keylist;
|
||||
ta->keylist = k;
|
||||
lock_basic_unlock(&ta->lock);
|
||||
return ta;
|
||||
}
|
||||
|
||||
|
|
@ -895,15 +933,20 @@ anchors_assemble_rrsets(struct val_anchors* anchors)
|
|||
struct trust_anchor* ta;
|
||||
struct trust_anchor* next;
|
||||
size_t nods, nokey;
|
||||
lock_basic_lock(&anchors->lock);
|
||||
ta=(struct trust_anchor*)rbtree_first(anchors->tree);
|
||||
while((rbnode_t*)ta != RBTREE_NULL) {
|
||||
next = (struct trust_anchor*)rbtree_next(&ta->node);
|
||||
lock_basic_lock(&ta->lock);
|
||||
if(ta->numDS == 0 && ta->numDNSKEY == 0) {
|
||||
lock_basic_unlock(&ta->lock);
|
||||
ta = next; /* skip unsigned entries, nothing to do */
|
||||
continue;
|
||||
}
|
||||
if(!anchors_assemble(anchors, ta)) {
|
||||
log_err("out of memory");
|
||||
lock_basic_unlock(&ta->lock);
|
||||
lock_basic_unlock(&anchors->lock);
|
||||
return 0;
|
||||
}
|
||||
nods = anchors_ds_unsupported(ta);
|
||||
|
|
@ -926,8 +969,10 @@ anchors_assemble_rrsets(struct val_anchors* anchors)
|
|||
" upgrade unbound and openssl)", b);
|
||||
(void)rbtree_delete(anchors->tree, &ta->node);
|
||||
}
|
||||
lock_basic_unlock(&ta->lock);
|
||||
ta = next;
|
||||
}
|
||||
lock_basic_unlock(&anchors->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -982,27 +1027,35 @@ anchors_apply_cfg(struct val_anchors* anchors, struct config_file* cfg)
|
|||
}
|
||||
}
|
||||
if(cfg->dlv_anchor_file && cfg->dlv_anchor_file[0] != 0) {
|
||||
struct trust_anchor* dlva;
|
||||
nm = cfg->dlv_anchor_file;
|
||||
if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm,
|
||||
cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
|
||||
nm += strlen(cfg->chrootdir);
|
||||
if(!(anchors->dlv_anchor = anchor_read_file(anchors, parsebuf,
|
||||
if(!(dlva = anchor_read_file(anchors, parsebuf,
|
||||
nm, 1))) {
|
||||
log_err("error reading dlv-anchor-file: %s",
|
||||
cfg->dlv_anchor_file);
|
||||
ldns_buffer_free(parsebuf);
|
||||
return 0;
|
||||
}
|
||||
lock_basic_lock(&anchors->lock);
|
||||
anchors->dlv_anchor = dlva;
|
||||
lock_basic_unlock(&anchors->lock);
|
||||
}
|
||||
for(f = cfg->dlv_anchor_list; f; f = f->next) {
|
||||
struct trust_anchor* dlva;
|
||||
if(!f->str || f->str[0] == 0) /* empty "" */
|
||||
continue;
|
||||
if(!(anchors->dlv_anchor = anchor_store_str(
|
||||
if(!(dlva = anchor_store_str(
|
||||
anchors, parsebuf, f->str))) {
|
||||
log_err("error in dlv-anchor: \"%s\"", f->str);
|
||||
ldns_buffer_free(parsebuf);
|
||||
return 0;
|
||||
}
|
||||
lock_basic_lock(&anchors->lock);
|
||||
anchors->dlv_anchor = dlva;
|
||||
lock_basic_unlock(&anchors->lock);
|
||||
}
|
||||
for(f = cfg->auto_trust_anchor_file_list; f; f = f->next) {
|
||||
if(!f->str || f->str[0] == 0) /* empty "" */
|
||||
|
|
@ -1011,7 +1064,7 @@ anchors_apply_cfg(struct val_anchors* anchors, struct config_file* cfg)
|
|||
if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm,
|
||||
cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
|
||||
nm += strlen(cfg->chrootdir);
|
||||
if(!autr_read_file(anchors, parsebuf, nm)) {
|
||||
if(!autr_read_file(anchors, nm)) {
|
||||
log_err("error reading auto-trust-anchor-file: %s",
|
||||
f->str);
|
||||
ldns_buffer_free(parsebuf);
|
||||
|
|
@ -1037,6 +1090,7 @@ anchors_lookup(struct val_anchors* anchors,
|
|||
key.namelabs = dname_count_labels(qname);
|
||||
key.namelen = qname_len;
|
||||
key.dclass = qclass;
|
||||
lock_basic_lock(&anchors->lock);
|
||||
if(rbtree_find_less_equal(anchors->tree, &key, &res)) {
|
||||
/* exact */
|
||||
result = (struct trust_anchor*)res;
|
||||
|
|
@ -1044,8 +1098,10 @@ anchors_lookup(struct val_anchors* anchors,
|
|||
/* smaller element (or no element) */
|
||||
int m;
|
||||
result = (struct trust_anchor*)res;
|
||||
if(!result || result->dclass != qclass)
|
||||
if(!result || result->dclass != qclass) {
|
||||
lock_basic_unlock(&anchors->lock);
|
||||
return NULL;
|
||||
}
|
||||
/* count number of labels matched */
|
||||
(void)dname_lab_cmp(result->name, result->namelabs, key.name,
|
||||
key.namelabs, &m);
|
||||
|
|
@ -1055,6 +1111,10 @@ anchors_lookup(struct val_anchors* anchors,
|
|||
result = result->parent;
|
||||
}
|
||||
}
|
||||
if(result) {
|
||||
lock_basic_lock(&result->lock);
|
||||
}
|
||||
lock_basic_unlock(&anchors->lock);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,11 +42,11 @@
|
|||
#ifndef VALIDATOR_VAL_ANCHOR_H
|
||||
#define VALIDATOR_VAL_ANCHOR_H
|
||||
#include "util/rbtree.h"
|
||||
#include "util/locks.h"
|
||||
struct regional;
|
||||
struct trust_anchor;
|
||||
struct config_file;
|
||||
struct ub_packed_rrset_key;
|
||||
struct autr_ta_data;
|
||||
struct autr_point_data;
|
||||
struct autr_global_data;
|
||||
|
||||
|
|
@ -54,6 +54,8 @@ struct autr_global_data;
|
|||
* Trust anchor store.
|
||||
*/
|
||||
struct val_anchors {
|
||||
/** lock on trees */
|
||||
lock_basic_t lock;
|
||||
/** region where trust anchors are allocated */
|
||||
struct regional* region;
|
||||
/**
|
||||
|
|
@ -81,8 +83,6 @@ struct ta_key {
|
|||
size_t len;
|
||||
/** DNS type (host format) of the key, DS or DNSKEY */
|
||||
uint16_t type;
|
||||
/** Autotrust ta key state, or NULL */
|
||||
struct autr_ta_data* autr;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -92,6 +92,8 @@ struct ta_key {
|
|||
struct trust_anchor {
|
||||
/** rbtree node, key is this structure */
|
||||
rbnode_t node;
|
||||
/** lock on the entire anchor and its keys; for autotrust changes */
|
||||
lock_basic_t lock;
|
||||
/** name of this trust anchor */
|
||||
uint8_t* name;
|
||||
/** length of name */
|
||||
|
|
@ -147,7 +149,7 @@ int anchors_apply_cfg(struct val_anchors* anchors, struct config_file* cfg);
|
|||
* @param qname: query name, uncompressed wireformat.
|
||||
* @param qname_len: length of qname.
|
||||
* @param qclass: class to query for.
|
||||
* @return the trust anchor or NULL if none is found.
|
||||
* @return the trust anchor or NULL if none is found. The anchor is locked.
|
||||
*/
|
||||
struct trust_anchor* anchors_lookup(struct val_anchors* anchors,
|
||||
uint8_t* qname, size_t qname_len, uint16_t qclass);
|
||||
|
|
@ -159,7 +161,7 @@ struct trust_anchor* anchors_lookup(struct val_anchors* anchors,
|
|||
* @param namelabs: labels in name
|
||||
* @param namelen: length of name
|
||||
* @param dclass: class of trust anchor
|
||||
* @return NULL if not found.
|
||||
* @return NULL if not found. The anchor is locked.
|
||||
*/
|
||||
struct trust_anchor* anchor_find(struct val_anchors* anchors,
|
||||
uint8_t* name, int namelabs, size_t namelen, uint16_t dclass);
|
||||
|
|
|
|||
|
|
@ -712,6 +712,17 @@ val_check_nonsecure(struct val_env* ve, struct reply_info* rep)
|
|||
}
|
||||
}
|
||||
|
||||
/** check no anchor and unlock */
|
||||
static int
|
||||
check_no_anchor(struct val_anchors* anchors, uint8_t* nm, size_t l, uint16_t c)
|
||||
{
|
||||
struct trust_anchor* ta;
|
||||
if((ta=anchors_lookup(anchors, nm, l, c))) {
|
||||
lock_basic_unlock(&ta->lock);
|
||||
}
|
||||
return !ta;
|
||||
}
|
||||
|
||||
void
|
||||
val_mark_indeterminate(struct reply_info* rep, struct val_anchors* anchors,
|
||||
struct rrset_cache* r, struct module_env* env)
|
||||
|
|
@ -721,7 +732,7 @@ val_mark_indeterminate(struct reply_info* rep, struct val_anchors* anchors,
|
|||
for(i=0; i<rep->rrset_count; i++) {
|
||||
d = (struct packed_rrset_data*)rep->rrsets[i]->entry.data;
|
||||
if(d->security == sec_status_unchecked &&
|
||||
!anchors_lookup(anchors, rep->rrsets[i]->rk.dname,
|
||||
check_no_anchor(anchors, rep->rrsets[i]->rk.dname,
|
||||
rep->rrsets[i]->rk.dname_len,
|
||||
ntohs(rep->rrsets[i]->rk.rrset_class)))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#include "validator/val_nsec.h"
|
||||
#include "validator/val_nsec3.h"
|
||||
#include "validator/val_neg.h"
|
||||
#include "validator/autotrust.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/module.h"
|
||||
|
|
@ -372,6 +373,15 @@ prime_trust_anchor(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
* query, and its a 'normal' for iterator as well */
|
||||
vq->wait_prime_ta = 1; /* to elicit PRIME_RESP_STATE processing
|
||||
from the validator inform_super() routine */
|
||||
/* store trust anchor name for later lookup when prime returns */
|
||||
vq->trust_anchor_name = regional_alloc_init(qstate->region,
|
||||
toprime->name, toprime->namelen);
|
||||
vq->trust_anchor_len = toprime->namelen;
|
||||
vq->trust_anchor_labs = toprime->namelabs;
|
||||
if(!vq->trust_anchor_name) {
|
||||
log_err("Could not prime trust anchor: out of memory");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -1160,6 +1170,7 @@ processInit(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
{
|
||||
uint8_t* lookup_name;
|
||||
size_t lookup_len;
|
||||
struct trust_anchor* anchor;
|
||||
enum val_classification subtype = val_classify_response(
|
||||
qstate->query_flags, &qstate->qinfo, &vq->qchase,
|
||||
vq->orig_msg->rep, vq->rrset_skip);
|
||||
|
|
@ -1197,7 +1208,7 @@ processInit(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
vq->key_entry = NULL;
|
||||
vq->empty_DS_name = NULL;
|
||||
vq->ds_rrset = 0;
|
||||
vq->trust_anchor = anchors_lookup(qstate->env->anchors,
|
||||
anchor = anchors_lookup(qstate->env->anchors,
|
||||
lookup_name, lookup_len, vq->qchase.qclass);
|
||||
|
||||
/* Determine the signer/lookup name */
|
||||
|
|
@ -1216,13 +1227,11 @@ processInit(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
|
||||
/* for NXDOMAIN it could be signed by a parent of the trust anchor */
|
||||
if(subtype == VAL_CLASS_NAMEERROR && vq->signer_name &&
|
||||
vq->trust_anchor &&
|
||||
dname_strict_subdomain_c(vq->trust_anchor->name, lookup_name)){
|
||||
while(vq->trust_anchor && dname_strict_subdomain_c(
|
||||
vq->trust_anchor->name, lookup_name)) {
|
||||
vq->trust_anchor = vq->trust_anchor->parent;
|
||||
}
|
||||
if(!vq->trust_anchor) { /* unsigned parent denies anchor*/
|
||||
anchor && dname_strict_subdomain_c(anchor->name, lookup_name)){
|
||||
lock_basic_unlock(&anchor->lock);
|
||||
anchor = anchors_lookup(qstate->env->anchors,
|
||||
lookup_name, lookup_len, vq->qchase.qclass);
|
||||
if(!anchor) { /* unsigned parent denies anchor*/
|
||||
verbose(VERB_QUERY, "unsigned parent zone denies"
|
||||
" trust anchor, indeterminate");
|
||||
vq->chase_reply->security = sec_status_indeterminate;
|
||||
|
|
@ -1248,7 +1257,7 @@ processInit(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
vq->qchase.qclass, qstate->region, *qstate->env->now);
|
||||
|
||||
/* there is no key(from DLV) and no trust anchor */
|
||||
if(vq->key_entry == NULL && vq->trust_anchor == NULL) {
|
||||
if(vq->key_entry == NULL && anchor == NULL) {
|
||||
/*response isn't under a trust anchor, so we cannot validate.*/
|
||||
vq->chase_reply->security = sec_status_indeterminate;
|
||||
/* go to finished state to cache this result */
|
||||
|
|
@ -1257,16 +1266,14 @@ processInit(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
}
|
||||
/* if not key, or if keyentry is *above* the trustanchor, i.e.
|
||||
* the keyentry is based on another (higher) trustanchor */
|
||||
else if(vq->key_entry == NULL || (vq->trust_anchor &&
|
||||
dname_strict_subdomain_c(vq->trust_anchor->name,
|
||||
vq->key_entry->name))) {
|
||||
else if(vq->key_entry == NULL || (anchor &&
|
||||
dname_strict_subdomain_c(anchor->name, vq->key_entry->name))) {
|
||||
/* trust anchor is an 'unsigned' trust anchor */
|
||||
if(vq->trust_anchor && vq->trust_anchor->numDS == 0 &&
|
||||
vq->trust_anchor->numDNSKEY == 0) {
|
||||
if(anchor && anchor->numDS == 0 && anchor->numDNSKEY == 0) {
|
||||
vq->chase_reply->security = sec_status_insecure;
|
||||
val_mark_insecure(vq->chase_reply,
|
||||
vq->trust_anchor->name,
|
||||
val_mark_insecure(vq->chase_reply, anchor->name,
|
||||
qstate->env->rrset_cache, qstate->env);
|
||||
lock_basic_unlock(&anchor->lock);
|
||||
vq->dlv_checked=1; /* skip DLV check */
|
||||
/* go to finished state to cache this result */
|
||||
vq->state = VAL_FINISHED_STATE;
|
||||
|
|
@ -1274,13 +1281,21 @@ processInit(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
}
|
||||
/* fire off a trust anchor priming query. */
|
||||
verbose(VERB_DETAIL, "prime trust anchor");
|
||||
if(!prime_trust_anchor(qstate, vq, id, vq->trust_anchor))
|
||||
if(!prime_trust_anchor(qstate, vq, id, anchor)) {
|
||||
lock_basic_unlock(&anchor->lock);
|
||||
return val_error(qstate, id);
|
||||
}
|
||||
lock_basic_unlock(&anchor->lock);
|
||||
/* and otherwise, don't continue processing this event.
|
||||
* (it will be reactivated when the priming query returns). */
|
||||
vq->state = VAL_FINDKEY_STATE;
|
||||
return 0;
|
||||
} else if(key_entry_isnull(vq->key_entry)) {
|
||||
}
|
||||
if(anchor) {
|
||||
lock_basic_unlock(&anchor->lock);
|
||||
}
|
||||
|
||||
if(key_entry_isnull(vq->key_entry)) {
|
||||
/* response is under a null key, so we cannot validate
|
||||
* However, we do set the status to INSECURE, since it is
|
||||
* essentially proven insecure. */
|
||||
|
|
@ -2031,8 +2046,8 @@ val_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
|||
/**
|
||||
* Evaluate the response to a priming request.
|
||||
*
|
||||
* @param rcode: rcode return value.
|
||||
* @param msg: message return value (allocated in a the wrong region).
|
||||
* @param dnskey_rrset: DNSKEY rrset (can be NULL if none) in prime reply.
|
||||
* (this rrset is allocated in the wrong region, not the qstate).
|
||||
* @param ta: trust anchor.
|
||||
* @param qstate: qstate that needs key.
|
||||
* @param id: module id.
|
||||
|
|
@ -2042,19 +2057,13 @@ val_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
|||
* Bad key (validation failed).
|
||||
*/
|
||||
static struct key_entry_key*
|
||||
primeResponseToKE(int rcode, struct dns_msg* msg, struct trust_anchor* ta,
|
||||
struct module_qstate* qstate, int id)
|
||||
primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
|
||||
struct trust_anchor* ta, struct module_qstate* qstate, int id)
|
||||
{
|
||||
struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
|
||||
struct ub_packed_rrset_key* dnskey_rrset = NULL;
|
||||
struct key_entry_key* kkey = NULL;
|
||||
enum sec_status sec = sec_status_unchecked;
|
||||
|
||||
if(rcode == LDNS_RCODE_NOERROR) {
|
||||
dnskey_rrset = reply_find_rrset_section_an(msg->rep,
|
||||
ta->name, ta->namelen, LDNS_RR_TYPE_DNSKEY,
|
||||
ta->dclass);
|
||||
}
|
||||
if(!dnskey_rrset) {
|
||||
log_nametypeclass(VERB_OPS, "failed to prime trust anchor -- "
|
||||
"could not fetch DNSKEY rrset",
|
||||
|
|
@ -2069,7 +2078,6 @@ primeResponseToKE(int rcode, struct dns_msg* msg, struct trust_anchor* ta,
|
|||
log_err("out of memory: allocate fail prime key");
|
||||
return NULL;
|
||||
}
|
||||
key_cache_insert(ve->kcache, kkey);
|
||||
return kkey;
|
||||
}
|
||||
/* attempt to verify with trust anchor DS and DNSKEY */
|
||||
|
|
@ -2119,14 +2127,11 @@ primeResponseToKE(int rcode, struct dns_msg* msg, struct trust_anchor* ta,
|
|||
log_err("out of memory: allocate null prime key");
|
||||
return NULL;
|
||||
}
|
||||
key_cache_insert(ve->kcache, kkey);
|
||||
return kkey;
|
||||
}
|
||||
|
||||
log_nametypeclass(VERB_DETAIL, "Successfully primed trust anchor",
|
||||
ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass);
|
||||
/* store the freshly primed entry in the cache */
|
||||
key_cache_insert(ve->kcache, kkey);
|
||||
return kkey;
|
||||
}
|
||||
|
||||
|
|
@ -2422,10 +2427,39 @@ static void
|
|||
process_prime_response(struct module_qstate* qstate, struct val_qstate* vq,
|
||||
int id, int rcode, struct dns_msg* msg)
|
||||
{
|
||||
struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
|
||||
struct ub_packed_rrset_key* dnskey_rrset = NULL;
|
||||
struct trust_anchor* ta = anchor_find(qstate->env->anchors,
|
||||
vq->trust_anchor_name, vq->trust_anchor_labs,
|
||||
vq->trust_anchor_len, vq->qchase.qclass);
|
||||
if(!ta) {
|
||||
/* trust anchor revoked, restart with less anchors */
|
||||
vq->state = VAL_INIT_STATE;
|
||||
if(!vq->trust_anchor_name)
|
||||
vq->state = VAL_VALIDATE_STATE; /* break a loop */
|
||||
vq->trust_anchor_name = NULL;
|
||||
return;
|
||||
}
|
||||
/* Fetch and validate the keyEntry that corresponds to the
|
||||
* current trust anchor. */
|
||||
vq->key_entry = primeResponseToKE(rcode, msg, vq->trust_anchor,
|
||||
qstate, id);
|
||||
if(rcode == LDNS_RCODE_NOERROR) {
|
||||
dnskey_rrset = reply_find_rrset_section_an(msg->rep,
|
||||
ta->name, ta->namelen, LDNS_RR_TYPE_DNSKEY,
|
||||
ta->dclass);
|
||||
}
|
||||
if(ta->autr) {
|
||||
if(!autr_process_prime(qstate->env, ve, ta, dnskey_rrset)) {
|
||||
/* trust anchor revoked, restart with less anchors */
|
||||
vq->state = VAL_INIT_STATE;
|
||||
vq->trust_anchor_name = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
vq->key_entry = primeResponseToKE(dnskey_rrset, ta, qstate, id);
|
||||
lock_basic_unlock(&ta->lock);
|
||||
if(vq->key_entry)
|
||||
/* store the freshly primed entry in the cache */
|
||||
key_cache_insert(ve->kcache, vq->key_entry);
|
||||
|
||||
/* If the result of the prime is a null key, skip the FINDKEY state.*/
|
||||
if(!vq->key_entry || key_entry_isnull(vq->key_entry) ||
|
||||
|
|
|
|||
|
|
@ -177,8 +177,12 @@ struct val_qstate {
|
|||
*/
|
||||
size_t rrset_skip;
|
||||
|
||||
/** the trust anchor rrset */
|
||||
struct trust_anchor* trust_anchor;
|
||||
/** trust anchor name */
|
||||
uint8_t* trust_anchor_name;
|
||||
/** trust anchor labels */
|
||||
int trust_anchor_labs;
|
||||
/** trust anchor length */
|
||||
size_t trust_anchor_len;
|
||||
|
||||
/** the DS rrset */
|
||||
struct ub_packed_rrset_key* ds_rrset;
|
||||
|
|
|
|||
Loading…
Reference in a new issue