mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
Work on validation of multiple algorithms.
git-svn-id: file:///svn/unbound/trunk@2356 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
c4c8a65ff2
commit
e9582487d9
8 changed files with 341 additions and 62 deletions
|
|
@ -148,6 +148,33 @@ should_be_bogus(struct ub_packed_rrset_key* rrset, struct query_info* qinfo)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** return number of rrs in an rrset */
|
||||||
|
static size_t
|
||||||
|
rrset_get_count(struct ub_packed_rrset_key* rrset)
|
||||||
|
{
|
||||||
|
struct packed_rrset_data* d = (struct packed_rrset_data*)
|
||||||
|
rrset->entry.data;
|
||||||
|
if(!d) return 0;
|
||||||
|
return d->count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** setup sig alg list from dnskey */
|
||||||
|
static void
|
||||||
|
setup_sigalg(struct ub_packed_rrset_key* dnskey, uint8_t* sigalg)
|
||||||
|
{
|
||||||
|
uint8_t a[ALGO_NEEDS_MAX];
|
||||||
|
size_t i, n = 0;
|
||||||
|
memset(a, 0, sizeof(a));
|
||||||
|
for(i=0; i<rrset_get_count(dnskey); i++) {
|
||||||
|
uint8_t algo = dnskey_get_algo(dnskey, i);
|
||||||
|
if(a[algo] == 0) {
|
||||||
|
a[algo] = 1;
|
||||||
|
sigalg[n++] = algo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sigalg[n] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** verify and test one rrset against the key rrset */
|
/** verify and test one rrset against the key rrset */
|
||||||
static void
|
static void
|
||||||
verifytest_rrset(struct module_env* env, struct val_env* ve,
|
verifytest_rrset(struct module_env* env, struct val_env* ve,
|
||||||
|
|
@ -156,12 +183,14 @@ verifytest_rrset(struct module_env* env, struct val_env* ve,
|
||||||
{
|
{
|
||||||
enum sec_status sec;
|
enum sec_status sec;
|
||||||
char* reason = NULL;
|
char* reason = NULL;
|
||||||
|
uint8_t sigalg[ALGO_NEEDS_MAX+1];
|
||||||
if(vsig) {
|
if(vsig) {
|
||||||
log_nametypeclass(VERB_QUERY, "verify of rrset",
|
log_nametypeclass(VERB_QUERY, "verify of rrset",
|
||||||
rrset->rk.dname, ntohs(rrset->rk.type),
|
rrset->rk.dname, ntohs(rrset->rk.type),
|
||||||
ntohs(rrset->rk.rrset_class));
|
ntohs(rrset->rk.rrset_class));
|
||||||
}
|
}
|
||||||
sec = dnskeyset_verify_rrset(env, ve, rrset, dnskey, 1, &reason);
|
setup_sigalg(dnskey, sigalg); /* check all algorithms in the dnskey */
|
||||||
|
sec = dnskeyset_verify_rrset(env, ve, rrset, dnskey, sigalg, &reason);
|
||||||
if(vsig) {
|
if(vsig) {
|
||||||
printf("verify outcome is: %s %s\n", sec_status_to_string(sec),
|
printf("verify outcome is: %s %s\n", sec_status_to_string(sec),
|
||||||
reason?reason:"");
|
reason?reason:"");
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,8 @@ key_entry_sizefunc(void* key, void* data)
|
||||||
s += packed_rrset_sizeof(kd->rrset_data);
|
s += packed_rrset_sizeof(kd->rrset_data);
|
||||||
if(kd->reason)
|
if(kd->reason)
|
||||||
s += strlen(kd->reason)+1;
|
s += strlen(kd->reason)+1;
|
||||||
|
if(kd->algo)
|
||||||
|
s += strlen((char*)kd->algo)+1;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -91,6 +93,7 @@ key_entry_deldatafunc(void* data, void* ATTR_UNUSED(userarg))
|
||||||
struct key_entry_data* kd = (struct key_entry_data*)data;
|
struct key_entry_data* kd = (struct key_entry_data*)data;
|
||||||
free(kd->reason);
|
free(kd->reason);
|
||||||
free(kd->rrset_data);
|
free(kd->rrset_data);
|
||||||
|
free(kd->algo);
|
||||||
free(kd);
|
free(kd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,6 +139,12 @@ key_entry_copy_toregion(struct key_entry_key* kkey, struct regional* region)
|
||||||
if(!newd->reason)
|
if(!newd->reason)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if(d->algo) {
|
||||||
|
newd->algo = (uint8_t*)regional_strdup(region,
|
||||||
|
(char*)d->algo);
|
||||||
|
if(!newd->algo)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
newk->entry.data = newd;
|
newk->entry.data = newd;
|
||||||
}
|
}
|
||||||
return newk;
|
return newk;
|
||||||
|
|
@ -190,6 +199,17 @@ key_entry_copy(struct key_entry_key* kkey)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(d->algo) {
|
||||||
|
newd->algo = (uint8_t*)strdup((char*)d->algo);
|
||||||
|
if(!newd->algo) {
|
||||||
|
free(newd->rrset_data);
|
||||||
|
free(newd->reason);
|
||||||
|
free(newd);
|
||||||
|
free(newk->name);
|
||||||
|
free(newk);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
newk->entry.data = newd;
|
newk->entry.data = newd;
|
||||||
}
|
}
|
||||||
return newk;
|
return newk;
|
||||||
|
|
@ -267,13 +287,14 @@ key_entry_create_null(struct regional* region,
|
||||||
d->reason = NULL;
|
d->reason = NULL;
|
||||||
d->rrset_type = LDNS_RR_TYPE_DNSKEY;
|
d->rrset_type = LDNS_RR_TYPE_DNSKEY;
|
||||||
d->rrset_data = NULL;
|
d->rrset_data = NULL;
|
||||||
|
d->algo = NULL;
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct key_entry_key*
|
struct key_entry_key*
|
||||||
key_entry_create_rrset(struct regional* region,
|
key_entry_create_rrset(struct regional* region,
|
||||||
uint8_t* name, size_t namelen, uint16_t dclass,
|
uint8_t* name, size_t namelen, uint16_t dclass,
|
||||||
struct ub_packed_rrset_key* rrset, uint32_t now)
|
struct ub_packed_rrset_key* rrset, uint8_t* sigalg, uint32_t now)
|
||||||
{
|
{
|
||||||
struct key_entry_key* k;
|
struct key_entry_key* k;
|
||||||
struct key_entry_data* d;
|
struct key_entry_data* d;
|
||||||
|
|
@ -289,6 +310,11 @@ key_entry_create_rrset(struct regional* region,
|
||||||
rd, packed_rrset_sizeof(rd));
|
rd, packed_rrset_sizeof(rd));
|
||||||
if(!d->rrset_data)
|
if(!d->rrset_data)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
if(sigalg) {
|
||||||
|
d->algo = (uint8_t*)regional_strdup(region, (char*)sigalg);
|
||||||
|
if(!d->algo)
|
||||||
|
return NULL;
|
||||||
|
} else d->algo = NULL;
|
||||||
packed_rrset_ptr_fixup(d->rrset_data);
|
packed_rrset_ptr_fixup(d->rrset_data);
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
@ -307,6 +333,7 @@ key_entry_create_bad(struct regional* region,
|
||||||
d->reason = NULL;
|
d->reason = NULL;
|
||||||
d->rrset_type = LDNS_RR_TYPE_DNSKEY;
|
d->rrset_type = LDNS_RR_TYPE_DNSKEY;
|
||||||
d->rrset_data = NULL;
|
d->rrset_data = NULL;
|
||||||
|
d->algo = NULL;
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,8 @@ struct key_entry_data {
|
||||||
struct packed_rrset_data* rrset_data;
|
struct packed_rrset_data* rrset_data;
|
||||||
/** not NULL sometimes to give reason why bogus */
|
/** not NULL sometimes to give reason why bogus */
|
||||||
char* reason;
|
char* reason;
|
||||||
|
/** list of algorithms signalled, ends with 0, or NULL */
|
||||||
|
uint8_t* algo;
|
||||||
/** DNS RR type of the rrset data (host order) */
|
/** DNS RR type of the rrset data (host order) */
|
||||||
uint16_t rrset_type;
|
uint16_t rrset_type;
|
||||||
/** if the key is bad: Bogus or malformed */
|
/** if the key is bad: Bogus or malformed */
|
||||||
|
|
@ -177,12 +179,13 @@ struct key_entry_key* key_entry_create_null(struct regional* region,
|
||||||
* @param namelen: length of name
|
* @param namelen: length of name
|
||||||
* @param dclass: class of key entry. (host order);
|
* @param dclass: class of key entry. (host order);
|
||||||
* @param rrset: data for key entry. This is copied to the region.
|
* @param rrset: data for key entry. This is copied to the region.
|
||||||
|
* @param sigalg: signalled algorithm list (or NULL).
|
||||||
* @param now: current time (added to ttl of rrset)
|
* @param now: current time (added to ttl of rrset)
|
||||||
* @return new key entry or NULL on alloc failure
|
* @return new key entry or NULL on alloc failure
|
||||||
*/
|
*/
|
||||||
struct key_entry_key* key_entry_create_rrset(struct regional* region,
|
struct key_entry_key* key_entry_create_rrset(struct regional* region,
|
||||||
uint8_t* name, size_t namelen, uint16_t dclass,
|
uint8_t* name, size_t namelen, uint16_t dclass,
|
||||||
struct ub_packed_rrset_key* rrset, uint32_t now);
|
struct ub_packed_rrset_key* rrset, uint8_t* sigalg, uint32_t now);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a bad entry, in the given region.
|
* Create a bad entry, in the given region.
|
||||||
|
|
|
||||||
|
|
@ -473,8 +473,45 @@ void algo_needs_init_dnskey(struct algo_needs* n,
|
||||||
n->num = total;
|
n->num = total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void algo_needs_init_dnskey_add(struct algo_needs* n,
|
||||||
|
struct ub_packed_rrset_key* dnskey, uint8_t* sigalg)
|
||||||
|
{
|
||||||
|
uint8_t algo;
|
||||||
|
size_t i, total = n->num;
|
||||||
|
size_t num = rrset_get_count(dnskey);
|
||||||
|
|
||||||
|
for(i=0; i<num; i++) {
|
||||||
|
algo = (uint8_t)dnskey_get_algo(dnskey, i);
|
||||||
|
if(!dnskey_algo_id_is_supported((int)algo))
|
||||||
|
continue;
|
||||||
|
if(n->needs[algo] == 0) {
|
||||||
|
n->needs[algo] = 1;
|
||||||
|
sigalg[total] = algo;
|
||||||
|
total++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sigalg[total] = 0;
|
||||||
|
n->num = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
void algo_needs_init_list(struct algo_needs* n, uint8_t* sigalg)
|
||||||
|
{
|
||||||
|
uint8_t algo;
|
||||||
|
size_t total = 0;
|
||||||
|
|
||||||
|
memset(n->needs, 0, sizeof(uint8_t)*ALGO_NEEDS_MAX);
|
||||||
|
while( (algo=*sigalg) != 0) {
|
||||||
|
log_assert(dnskey_algo_id_is_supported((int)algo));
|
||||||
|
log_assert(n->needs[algo] == 0);
|
||||||
|
n->needs[algo] = 1;
|
||||||
|
total++;
|
||||||
|
sigalg++;
|
||||||
|
}
|
||||||
|
n->num = total;
|
||||||
|
}
|
||||||
|
|
||||||
void algo_needs_init_ds(struct algo_needs* n, struct ub_packed_rrset_key* ds,
|
void algo_needs_init_ds(struct algo_needs* n, struct ub_packed_rrset_key* ds,
|
||||||
int fav_ds_algo)
|
int fav_ds_algo, uint8_t* sigalg)
|
||||||
{
|
{
|
||||||
uint8_t algo;
|
uint8_t algo;
|
||||||
size_t i, total = 0;
|
size_t i, total = 0;
|
||||||
|
|
@ -487,11 +524,14 @@ void algo_needs_init_ds(struct algo_needs* n, struct ub_packed_rrset_key* ds,
|
||||||
algo = (uint8_t)ds_get_key_algo(ds, i);
|
algo = (uint8_t)ds_get_key_algo(ds, i);
|
||||||
if(!dnskey_algo_id_is_supported((int)algo))
|
if(!dnskey_algo_id_is_supported((int)algo))
|
||||||
continue;
|
continue;
|
||||||
|
log_assert(algo != 0); /* we do not support 0 and is EOS */
|
||||||
if(n->needs[algo] == 0) {
|
if(n->needs[algo] == 0) {
|
||||||
n->needs[algo] = 1;
|
n->needs[algo] = 1;
|
||||||
|
sigalg[total] = algo;
|
||||||
total++;
|
total++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sigalg[total] = 0;
|
||||||
n->num = total;
|
n->num = total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -533,7 +573,7 @@ int algo_needs_missing(struct algo_needs* n)
|
||||||
enum sec_status
|
enum sec_status
|
||||||
dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
|
dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
|
||||||
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
|
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
|
||||||
int downprot, char** reason)
|
uint8_t* sigalg, char** reason)
|
||||||
{
|
{
|
||||||
enum sec_status sec;
|
enum sec_status sec;
|
||||||
size_t i, num;
|
size_t i, num;
|
||||||
|
|
@ -550,30 +590,32 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
|
||||||
return sec_status_bogus;
|
return sec_status_bogus;
|
||||||
}
|
}
|
||||||
|
|
||||||
algo_needs_init_dnskey(&needs, dnskey);
|
if(sigalg) {
|
||||||
|
algo_needs_init_list(&needs, sigalg);
|
||||||
if(algo_needs_num_missing(&needs) == 0) {
|
if(algo_needs_num_missing(&needs) == 0) {
|
||||||
verbose(VERB_QUERY, "DNSKEY has no known algorithms");
|
verbose(VERB_QUERY, "zone has no known algorithms");
|
||||||
*reason = "DNSKEY has no known algorithms";
|
*reason = "zone has no known algorithms";
|
||||||
return sec_status_insecure;
|
return sec_status_insecure;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for(i=0; i<num; i++) {
|
for(i=0; i<num; i++) {
|
||||||
sec = dnskeyset_verify_rrset_sig(env, ve, *env->now, rrset,
|
sec = dnskeyset_verify_rrset_sig(env, ve, *env->now, rrset,
|
||||||
dnskey, i, &sortree, reason);
|
dnskey, i, &sortree, reason);
|
||||||
/* see which algorithm has been fixed up */
|
/* see which algorithm has been fixed up */
|
||||||
if(sec == sec_status_secure) {
|
if(sec == sec_status_secure) {
|
||||||
if(!downprot)
|
if(!sigalg)
|
||||||
return sec; /* done! */
|
return sec; /* done! */
|
||||||
else if(algo_needs_set_secure(&needs,
|
else if(algo_needs_set_secure(&needs,
|
||||||
(uint8_t)rrset_get_sig_algo(rrset, i)))
|
(uint8_t)rrset_get_sig_algo(rrset, i)))
|
||||||
return sec; /* done! */
|
return sec; /* done! */
|
||||||
} else if(downprot && sec == sec_status_bogus) {
|
} else if(sigalg && sec == sec_status_bogus) {
|
||||||
algo_needs_set_bogus(&needs,
|
algo_needs_set_bogus(&needs,
|
||||||
(uint8_t)rrset_get_sig_algo(rrset, i));
|
(uint8_t)rrset_get_sig_algo(rrset, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
verbose(VERB_ALGO, "rrset failed to verify: no valid signatures for "
|
verbose(VERB_ALGO, "rrset failed to verify: no valid signatures for "
|
||||||
"%d algorithms", (int)algo_needs_num_missing(&needs));
|
"%d algorithms", (int)algo_needs_num_missing(&needs));
|
||||||
if(downprot && (alg=algo_needs_missing(&needs)) != 0) {
|
if(sigalg && (alg=algo_needs_missing(&needs)) != 0) {
|
||||||
algo_needs_reason(env, alg, reason, "no signatures");
|
algo_needs_reason(env, alg, reason, "no signatures");
|
||||||
}
|
}
|
||||||
return sec_status_bogus;
|
return sec_status_bogus;
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ struct regional;
|
||||||
|
|
||||||
/** number of entries in algorithm needs array */
|
/** number of entries in algorithm needs array */
|
||||||
#define ALGO_NEEDS_MAX 256
|
#define ALGO_NEEDS_MAX 256
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Storage for algorithm needs. DNSKEY algorithms.
|
* Storage for algorithm needs. DNSKEY algorithms.
|
||||||
*/
|
*/
|
||||||
|
|
@ -75,14 +76,33 @@ struct algo_needs {
|
||||||
void algo_needs_init_dnskey(struct algo_needs* n,
|
void algo_needs_init_dnskey(struct algo_needs* n,
|
||||||
struct ub_packed_rrset_key* dnskey);
|
struct ub_packed_rrset_key* dnskey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize algo needs structure, set algos from rrset as needed.
|
||||||
|
* Results are added to an existing need structure.
|
||||||
|
* @param n: struct with storage.
|
||||||
|
* @param dnskey: algos from this struct set as necessary. DNSKEY set.
|
||||||
|
* @param sigalg: adds to signalled algorithm list too.
|
||||||
|
*/
|
||||||
|
void algo_needs_init_dnskey_add(struct algo_needs* n,
|
||||||
|
struct ub_packed_rrset_key* dnskey, uint8_t* sigalg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize algo needs structure from a signalled algo list.
|
||||||
|
* @param n: struct with storage.
|
||||||
|
* @param sigalg: signalled algorithm list, numbers ends with 0.
|
||||||
|
*/
|
||||||
|
void algo_needs_init_list(struct algo_needs* n, uint8_t* sigalg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize algo needs structure, set algos from rrset as needed.
|
* Initialize algo needs structure, set algos from rrset as needed.
|
||||||
* @param n: struct with storage.
|
* @param n: struct with storage.
|
||||||
* @param ds: algos from this struct set as necessary. DS set.
|
* @param ds: algos from this struct set as necessary. DS set.
|
||||||
* @param fav_ds_algo: filter to use only this DS algo.
|
* @param fav_ds_algo: filter to use only this DS algo.
|
||||||
|
* @param sigalg: list of signalled algos, constructed as output,
|
||||||
|
* provide size ALGO_NEEDS_MAX+1. list of algonumbers, ends with a zero.
|
||||||
*/
|
*/
|
||||||
void algo_needs_init_ds(struct algo_needs* n, struct ub_packed_rrset_key* ds,
|
void algo_needs_init_ds(struct algo_needs* n, struct ub_packed_rrset_key* ds,
|
||||||
int fav_ds_algo);
|
int fav_ds_algo, uint8_t* sigalg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark this algorithm as a success, sec_secure, and see if we are done.
|
* Mark this algorithm as a success, sec_secure, and see if we are done.
|
||||||
|
|
@ -221,7 +241,7 @@ uint16_t dnskey_get_flags(struct ub_packed_rrset_key* k, size_t idx);
|
||||||
* @param ve: validator environment, date settings.
|
* @param ve: validator environment, date settings.
|
||||||
* @param rrset: to be validated.
|
* @param rrset: to be validated.
|
||||||
* @param dnskey: DNSKEY rrset, keyset to try.
|
* @param dnskey: DNSKEY rrset, keyset to try.
|
||||||
* @param downprot: if true provide downgrade protection otherwise one
|
* @param sigalg: if nonNULL provide downgrade protection otherwise one
|
||||||
* algorithm is enough.
|
* algorithm is enough.
|
||||||
* @param reason: if bogus, a string returned, fixed or alloced in scratch.
|
* @param reason: if bogus, a string returned, fixed or alloced in scratch.
|
||||||
* @return SECURE if one key in the set verifies one rrsig.
|
* @return SECURE if one key in the set verifies one rrsig.
|
||||||
|
|
@ -230,7 +250,7 @@ uint16_t dnskey_get_flags(struct ub_packed_rrset_key* k, size_t idx);
|
||||||
*/
|
*/
|
||||||
enum sec_status dnskeyset_verify_rrset(struct module_env* env,
|
enum sec_status dnskeyset_verify_rrset(struct module_env* env,
|
||||||
struct val_env* ve, struct ub_packed_rrset_key* rrset,
|
struct val_env* ve, struct ub_packed_rrset_key* rrset,
|
||||||
struct ub_packed_rrset_key* dnskey, int downprot, char** reason);
|
struct ub_packed_rrset_key* dnskey, uint8_t* sigalg, char** reason);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* verify rrset against one specific dnskey (from rrset)
|
* verify rrset against one specific dnskey (from rrset)
|
||||||
|
|
|
||||||
|
|
@ -310,7 +310,7 @@ rrset_get_ttl(struct ub_packed_rrset_key* rrset)
|
||||||
enum sec_status
|
enum sec_status
|
||||||
val_verify_rrset(struct module_env* env, struct val_env* ve,
|
val_verify_rrset(struct module_env* env, struct val_env* ve,
|
||||||
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys,
|
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys,
|
||||||
int downprot, char** reason)
|
uint8_t* sigalg, char** reason)
|
||||||
{
|
{
|
||||||
enum sec_status sec;
|
enum sec_status sec;
|
||||||
struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
|
struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
|
||||||
|
|
@ -332,7 +332,7 @@ val_verify_rrset(struct module_env* env, struct val_env* ve,
|
||||||
}
|
}
|
||||||
log_nametypeclass(VERB_ALGO, "verify rrset", rrset->rk.dname,
|
log_nametypeclass(VERB_ALGO, "verify rrset", rrset->rk.dname,
|
||||||
ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class));
|
ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class));
|
||||||
sec = dnskeyset_verify_rrset(env, ve, rrset, keys, downprot, reason);
|
sec = dnskeyset_verify_rrset(env, ve, rrset, keys, sigalg, reason);
|
||||||
verbose(VERB_ALGO, "verify result: %s", sec_status_to_string(sec));
|
verbose(VERB_ALGO, "verify result: %s", sec_status_to_string(sec));
|
||||||
regional_free_all(env->scratch);
|
regional_free_all(env->scratch);
|
||||||
|
|
||||||
|
|
@ -378,7 +378,7 @@ val_verify_rrset_entry(struct module_env* env, struct val_env* ve,
|
||||||
dnskey.rk.dname_len = kkey->namelen;
|
dnskey.rk.dname_len = kkey->namelen;
|
||||||
dnskey.entry.key = &dnskey;
|
dnskey.entry.key = &dnskey;
|
||||||
dnskey.entry.data = kd->rrset_data;
|
dnskey.entry.data = kd->rrset_data;
|
||||||
sec = val_verify_rrset(env, ve, rrset, &dnskey, 1, reason);
|
sec = val_verify_rrset(env, ve, rrset, &dnskey, kd->algo, reason);
|
||||||
return sec;
|
return sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -453,7 +453,7 @@ int val_favorite_ds_algo(struct ub_packed_rrset_key* ds_rrset)
|
||||||
enum sec_status
|
enum sec_status
|
||||||
val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
|
val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
|
||||||
struct ub_packed_rrset_key* dnskey_rrset,
|
struct ub_packed_rrset_key* dnskey_rrset,
|
||||||
struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason)
|
struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason)
|
||||||
{
|
{
|
||||||
/* as long as this is false, we can consider this DS rrset to be
|
/* as long as this is false, we can consider this DS rrset to be
|
||||||
* equivalent to no DS rrset. */
|
* equivalent to no DS rrset. */
|
||||||
|
|
@ -472,8 +472,8 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
|
||||||
}
|
}
|
||||||
|
|
||||||
digest_algo = val_favorite_ds_algo(ds_rrset);
|
digest_algo = val_favorite_ds_algo(ds_rrset);
|
||||||
if(downprot)
|
if(sigalg)
|
||||||
algo_needs_init_ds(&needs, ds_rrset, digest_algo);
|
algo_needs_init_ds(&needs, ds_rrset, digest_algo, sigalg);
|
||||||
num = rrset_get_count(ds_rrset);
|
num = rrset_get_count(ds_rrset);
|
||||||
for(i=0; i<num; i++) {
|
for(i=0; i<num; i++) {
|
||||||
/* Check to see if we can understand this DS.
|
/* Check to see if we can understand this DS.
|
||||||
|
|
@ -492,12 +492,12 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
|
||||||
sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset,
|
sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset,
|
||||||
ds_rrset, i, reason);
|
ds_rrset, i, reason);
|
||||||
if(sec == sec_status_secure) {
|
if(sec == sec_status_secure) {
|
||||||
if(!downprot || algo_needs_set_secure(&needs,
|
if(!sigalg || algo_needs_set_secure(&needs,
|
||||||
(uint8_t)ds_get_key_algo(ds_rrset, i))) {
|
(uint8_t)ds_get_key_algo(ds_rrset, i))) {
|
||||||
verbose(VERB_ALGO, "DS matched DNSKEY.");
|
verbose(VERB_ALGO, "DS matched DNSKEY.");
|
||||||
return sec_status_secure;
|
return sec_status_secure;
|
||||||
}
|
}
|
||||||
} else if(downprot && sec == sec_status_bogus) {
|
} else if(sigalg && sec == sec_status_bogus) {
|
||||||
algo_needs_set_bogus(&needs,
|
algo_needs_set_bogus(&needs,
|
||||||
(uint8_t)ds_get_key_algo(ds_rrset, i));
|
(uint8_t)ds_get_key_algo(ds_rrset, i));
|
||||||
}
|
}
|
||||||
|
|
@ -513,7 +513,7 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
|
||||||
}
|
}
|
||||||
/* If any were understandable, then it is bad. */
|
/* If any were understandable, then it is bad. */
|
||||||
verbose(VERB_QUERY, "Failed to match any usable DS to a DNSKEY.");
|
verbose(VERB_QUERY, "Failed to match any usable DS to a DNSKEY.");
|
||||||
if(downprot && (alg=algo_needs_missing(&needs)) != 0) {
|
if(sigalg && (alg=algo_needs_missing(&needs)) != 0) {
|
||||||
algo_needs_reason(env, alg, reason, "missing verification of "
|
algo_needs_reason(env, alg, reason, "missing verification of "
|
||||||
"DNSKEY signature");
|
"DNSKEY signature");
|
||||||
}
|
}
|
||||||
|
|
@ -525,14 +525,15 @@ val_verify_new_DNSKEYs(struct regional* region, struct module_env* env,
|
||||||
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
|
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
|
||||||
struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason)
|
struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason)
|
||||||
{
|
{
|
||||||
|
uint8_t sigalg[ALGO_NEEDS_MAX+1];
|
||||||
enum sec_status sec = val_verify_DNSKEY_with_DS(env, ve,
|
enum sec_status sec = val_verify_DNSKEY_with_DS(env, ve,
|
||||||
dnskey_rrset, ds_rrset, downprot, reason);
|
dnskey_rrset, ds_rrset, downprot?sigalg:NULL, reason);
|
||||||
|
|
||||||
if(sec == sec_status_secure) {
|
if(sec == sec_status_secure) {
|
||||||
return key_entry_create_rrset(region,
|
return key_entry_create_rrset(region,
|
||||||
ds_rrset->rk.dname, ds_rrset->rk.dname_len,
|
ds_rrset->rk.dname, ds_rrset->rk.dname_len,
|
||||||
ntohs(ds_rrset->rk.rrset_class), dnskey_rrset,
|
ntohs(ds_rrset->rk.rrset_class), dnskey_rrset,
|
||||||
*env->now);
|
downprot?sigalg:NULL, *env->now);
|
||||||
} else if(sec == sec_status_insecure) {
|
} else if(sec == sec_status_insecure) {
|
||||||
return key_entry_create_null(region, ds_rrset->rk.dname,
|
return key_entry_create_null(region, ds_rrset->rk.dname,
|
||||||
ds_rrset->rk.dname_len,
|
ds_rrset->rk.dname_len,
|
||||||
|
|
@ -544,6 +545,147 @@ val_verify_new_DNSKEYs(struct regional* region, struct module_env* env,
|
||||||
BOGUS_KEY_TTL, *env->now);
|
BOGUS_KEY_TTL, *env->now);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum sec_status
|
||||||
|
val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
|
||||||
|
struct ub_packed_rrset_key* dnskey_rrset,
|
||||||
|
struct ub_packed_rrset_key* ta_ds,
|
||||||
|
struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason)
|
||||||
|
{
|
||||||
|
/* as long as this is false, we can consider this DS rrset to be
|
||||||
|
* equivalent to no DS rrset. */
|
||||||
|
int has_useful_ta = 0, digest_algo = 0, alg;
|
||||||
|
struct algo_needs needs;
|
||||||
|
size_t i, num;
|
||||||
|
enum sec_status sec;
|
||||||
|
|
||||||
|
if(ta_ds && (dnskey_rrset->rk.dname_len != ta_ds->rk.dname_len ||
|
||||||
|
query_dname_compare(dnskey_rrset->rk.dname, ta_ds->rk.dname)
|
||||||
|
!= 0)) {
|
||||||
|
verbose(VERB_QUERY, "DNSKEY RRset did not match DS RRset "
|
||||||
|
"by name");
|
||||||
|
*reason = "DNSKEY RRset did not match DS RRset by name";
|
||||||
|
return sec_status_bogus;
|
||||||
|
}
|
||||||
|
if(ta_dnskey && (dnskey_rrset->rk.dname_len != ta_dnskey->rk.dname_len
|
||||||
|
|| query_dname_compare(dnskey_rrset->rk.dname, ta_dnskey->rk.dname)
|
||||||
|
!= 0)) {
|
||||||
|
verbose(VERB_QUERY, "DNSKEY RRset did not match anchor RRset "
|
||||||
|
"by name");
|
||||||
|
*reason = "DNSKEY RRset did not match anchor RRset by name";
|
||||||
|
return sec_status_bogus;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ta_ds)
|
||||||
|
digest_algo = val_favorite_ds_algo(ta_ds);
|
||||||
|
if(sigalg) {
|
||||||
|
if(ta_ds)
|
||||||
|
algo_needs_init_ds(&needs, ta_ds, digest_algo, sigalg);
|
||||||
|
else memset(&needs, 0, sizeof(needs));
|
||||||
|
if(ta_dnskey)
|
||||||
|
algo_needs_init_dnskey_add(&needs, ta_dnskey, sigalg);
|
||||||
|
}
|
||||||
|
if(ta_ds) {
|
||||||
|
num = rrset_get_count(ta_ds);
|
||||||
|
for(i=0; i<num; i++) {
|
||||||
|
/* Check to see if we can understand this DS.
|
||||||
|
* And check it is the strongest digest */
|
||||||
|
if(!ds_digest_algo_is_supported(ta_ds, i) ||
|
||||||
|
!ds_key_algo_is_supported(ta_ds, i) ||
|
||||||
|
ds_get_digest_algo(ta_ds, i) != digest_algo) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Once we see a single DS with a known digestID and
|
||||||
|
* algorithm, we cannot return INSECURE (with a
|
||||||
|
* "null" KeyEntry). */
|
||||||
|
has_useful_ta = true;
|
||||||
|
|
||||||
|
sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset,
|
||||||
|
ta_ds, i, reason);
|
||||||
|
if(sec == sec_status_secure) {
|
||||||
|
if(!sigalg || algo_needs_set_secure(&needs,
|
||||||
|
(uint8_t)ds_get_key_algo(ta_ds, i))) {
|
||||||
|
verbose(VERB_ALGO, "DS matched DNSKEY.");
|
||||||
|
return sec_status_secure;
|
||||||
|
}
|
||||||
|
} else if(sigalg && sec == sec_status_bogus) {
|
||||||
|
algo_needs_set_bogus(&needs,
|
||||||
|
(uint8_t)ds_get_key_algo(ta_ds, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* None of the DS's worked out: check the DNSKEYs. */
|
||||||
|
if(ta_dnskey) {
|
||||||
|
num = rrset_get_count(ta_dnskey);
|
||||||
|
for(i=0; i<num; i++) {
|
||||||
|
/* Check to see if we can understand this DNSKEY */
|
||||||
|
if(!dnskey_algo_is_supported(ta_dnskey, i)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we saw a useful TA */
|
||||||
|
has_useful_ta = true;
|
||||||
|
|
||||||
|
sec = dnskey_verify_rrset(env, ve, dnskey_rrset,
|
||||||
|
ta_dnskey, i, reason);
|
||||||
|
if(sec == sec_status_secure) {
|
||||||
|
if(!sigalg || algo_needs_set_secure(&needs,
|
||||||
|
(uint8_t)dnskey_get_algo(ta_dnskey, i))) {
|
||||||
|
verbose(VERB_ALGO, "DS matched DNSKEY.");
|
||||||
|
return sec_status_secure;
|
||||||
|
}
|
||||||
|
} else if(sigalg && sec == sec_status_bogus) {
|
||||||
|
algo_needs_set_bogus(&needs,
|
||||||
|
(uint8_t)dnskey_get_algo(ta_dnskey, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* If no DSs were understandable, then this is OK. */
|
||||||
|
if(!has_useful_ta) {
|
||||||
|
verbose(VERB_ALGO, "No usable trust anchors were found -- "
|
||||||
|
"treating as insecure.");
|
||||||
|
return sec_status_insecure;
|
||||||
|
}
|
||||||
|
/* If any were understandable, then it is bad. */
|
||||||
|
verbose(VERB_QUERY, "Failed to match any usable anchor to a DNSKEY.");
|
||||||
|
if(sigalg && (alg=algo_needs_missing(&needs)) != 0) {
|
||||||
|
algo_needs_reason(env, alg, reason, "missing verification of "
|
||||||
|
"DNSKEY signature");
|
||||||
|
}
|
||||||
|
return sec_status_bogus;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct key_entry_key*
|
||||||
|
val_verify_new_DNSKEYs_with_ta(struct regional* region, struct module_env* env,
|
||||||
|
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
|
||||||
|
struct ub_packed_rrset_key* ta_ds_rrset,
|
||||||
|
struct ub_packed_rrset_key* ta_dnskey_rrset, int downprot,
|
||||||
|
char** reason)
|
||||||
|
{
|
||||||
|
uint8_t sigalg[ALGO_NEEDS_MAX+1];
|
||||||
|
enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve,
|
||||||
|
dnskey_rrset, ta_ds_rrset, ta_dnskey_rrset,
|
||||||
|
downprot?sigalg:NULL, reason);
|
||||||
|
|
||||||
|
if(sec == sec_status_secure) {
|
||||||
|
return key_entry_create_rrset(region,
|
||||||
|
dnskey_rrset->rk.dname, dnskey_rrset->rk.dname_len,
|
||||||
|
ntohs(dnskey_rrset->rk.rrset_class), dnskey_rrset,
|
||||||
|
downprot?sigalg:NULL, *env->now);
|
||||||
|
} else if(sec == sec_status_insecure) {
|
||||||
|
return key_entry_create_null(region, dnskey_rrset->rk.dname,
|
||||||
|
dnskey_rrset->rk.dname_len,
|
||||||
|
ntohs(dnskey_rrset->rk.rrset_class),
|
||||||
|
rrset_get_ttl(dnskey_rrset), *env->now);
|
||||||
|
}
|
||||||
|
return key_entry_create_bad(region, dnskey_rrset->rk.dname,
|
||||||
|
dnskey_rrset->rk.dname_len, ntohs(dnskey_rrset->rk.rrset_class),
|
||||||
|
BOGUS_KEY_TTL, *env->now);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
val_dsset_isusable(struct ub_packed_rrset_key* ds_rrset)
|
val_dsset_isusable(struct ub_packed_rrset_key* ds_rrset)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -117,14 +117,14 @@ void val_find_signer(enum val_classification subtype,
|
||||||
* @param ve: validator environment (verification settings)
|
* @param ve: validator environment (verification settings)
|
||||||
* @param rrset: what to verify
|
* @param rrset: what to verify
|
||||||
* @param keys: dnskey rrset to verify with.
|
* @param keys: dnskey rrset to verify with.
|
||||||
* @param downprot: if true provide downgrade protection otherwise one
|
* @param sigalg: if nonNULL provide downgrade protection otherwise one
|
||||||
* algorithm is enough.
|
* algorithm is enough. Algo list is constructed in here.
|
||||||
* @param reason: reason of failure. Fixed string or alloced in scratch.
|
* @param reason: reason of failure. Fixed string or alloced in scratch.
|
||||||
* @return security status of verification.
|
* @return security status of verification.
|
||||||
*/
|
*/
|
||||||
enum sec_status val_verify_rrset(struct module_env* env, struct val_env* ve,
|
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,
|
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys,
|
||||||
int downprot, char** reason);
|
uint8_t* sigalg, char** reason);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify RRset with keys from a keyset.
|
* Verify RRset with keys from a keyset.
|
||||||
|
|
@ -146,8 +146,9 @@ enum sec_status val_verify_rrset_entry(struct module_env* env,
|
||||||
* @param ve: validator environment (verification settings)
|
* @param ve: validator environment (verification settings)
|
||||||
* @param dnskey_rrset: DNSKEY rrset to verify
|
* @param dnskey_rrset: DNSKEY rrset to verify
|
||||||
* @param ds_rrset: DS rrset to verify with.
|
* @param ds_rrset: DS rrset to verify with.
|
||||||
* @param downprot: if true provide downgrade protection otherwise one
|
* @param sigalg: if nonNULL provide downgrade protection otherwise one
|
||||||
* algorithm is enough.
|
* algorithm is enough. The list of signalled algorithms is returned,
|
||||||
|
* must have enough space for ALGO_NEEDS_MAX+1.
|
||||||
* @param reason: reason of failure. Fixed string or alloced in scratch.
|
* @param reason: reason of failure. Fixed string or alloced in scratch.
|
||||||
* @return: sec_status_secure if a DS matches.
|
* @return: sec_status_secure if a DS matches.
|
||||||
* sec_status_insecure if end of trust (i.e., unknown algorithms).
|
* sec_status_insecure if end of trust (i.e., unknown algorithms).
|
||||||
|
|
@ -155,7 +156,7 @@ enum sec_status val_verify_rrset_entry(struct module_env* env,
|
||||||
*/
|
*/
|
||||||
enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env,
|
enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env,
|
||||||
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
|
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
|
||||||
struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason);
|
struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify new DNSKEYs with DS rrset. The DS contains hash values that should
|
* Verify new DNSKEYs with DS rrset. The DS contains hash values that should
|
||||||
|
|
@ -178,12 +179,43 @@ enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env,
|
||||||
* generally only occur in a private algorithm scenario: normally
|
* generally only occur in a private algorithm scenario: normally
|
||||||
* this sort of thing is checked before fetching the matching DNSKEY
|
* this sort of thing is checked before fetching the matching DNSKEY
|
||||||
* rrset.
|
* rrset.
|
||||||
|
* if downprot is set, a key entry with an algo list is made.
|
||||||
*/
|
*/
|
||||||
struct key_entry_key* val_verify_new_DNSKEYs(struct regional* region,
|
struct key_entry_key* val_verify_new_DNSKEYs(struct regional* region,
|
||||||
struct module_env* env, struct val_env* ve,
|
struct module_env* env, struct val_env* ve,
|
||||||
struct ub_packed_rrset_key* dnskey_rrset,
|
struct ub_packed_rrset_key* dnskey_rrset,
|
||||||
struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason);
|
struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify rrset with trust anchor: DS and DNSKEY rrset.
|
||||||
|
*
|
||||||
|
* @param region: where to allocate key entry result.
|
||||||
|
* @param env: module environment (scratch buffer)
|
||||||
|
* @param ve: validator environment (verification settings)
|
||||||
|
* @param dnskey_rrset: DNSKEY rrset to verify
|
||||||
|
* @param ta_ds_rrset: DS rrset to verify with.
|
||||||
|
* @param ta_dnskey_rrset: the DNSKEY rrset to verify with.
|
||||||
|
* @param downprot: if true provide downgrade protection otherwise one
|
||||||
|
* algorithm is enough.
|
||||||
|
* @param reason: reason of failure. Fixed string or alloced in scratch.
|
||||||
|
* @return a KeyEntry. This will either contain the now trusted
|
||||||
|
* dnskey_rrset, a "null" key entry indicating that this DS
|
||||||
|
* rrset/DNSKEY pair indicate an secure end to the island of trust
|
||||||
|
* (i.e., unknown algorithms), or a "bad" KeyEntry if the dnskey
|
||||||
|
* rrset fails to verify. Note that the "null" response should
|
||||||
|
* generally only occur in a private algorithm scenario: normally
|
||||||
|
* this sort of thing is checked before fetching the matching DNSKEY
|
||||||
|
* rrset.
|
||||||
|
* if downprot is set, a key entry with an algo list is made.
|
||||||
|
*/
|
||||||
|
struct key_entry_key* val_verify_new_DNSKEYs_with_ta(struct regional* region,
|
||||||
|
struct module_env* env, struct val_env* ve,
|
||||||
|
struct ub_packed_rrset_key* dnskey_rrset,
|
||||||
|
struct ub_packed_rrset_key* ta_ds_rrset,
|
||||||
|
struct ub_packed_rrset_key* ta_dnskey_rrset,
|
||||||
|
int downprot, char** reason);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if DS rrset is usable for validator or not.
|
* Determine if DS rrset is usable for validator or not.
|
||||||
* Returns true if the algorithms for key and DShash are supported,
|
* Returns true if the algorithms for key and DShash are supported,
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
#include "validator/val_nsec.h"
|
#include "validator/val_nsec.h"
|
||||||
#include "validator/val_nsec3.h"
|
#include "validator/val_nsec3.h"
|
||||||
#include "validator/val_neg.h"
|
#include "validator/val_neg.h"
|
||||||
|
#include "validator/val_sigcrypt.h"
|
||||||
#include "validator/autotrust.h"
|
#include "validator/autotrust.h"
|
||||||
#include "services/cache/dns.h"
|
#include "services/cache/dns.h"
|
||||||
#include "util/data/dname.h"
|
#include "util/data/dname.h"
|
||||||
|
|
@ -2260,11 +2261,10 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
|
||||||
return kkey;
|
return kkey;
|
||||||
}
|
}
|
||||||
/* attempt to verify with trust anchor DS and DNSKEY */
|
/* attempt to verify with trust anchor DS and DNSKEY */
|
||||||
if(ta->ds_rrset) {
|
kkey = val_verify_new_DNSKEYs_with_ta(qstate->region, qstate->env, ve,
|
||||||
kkey = val_verify_new_DNSKEYs(qstate->region, qstate->env, ve,
|
dnskey_rrset, ta->ds_rrset, ta->dnskey_rrset, 0, &reason);
|
||||||
dnskey_rrset, ta->ds_rrset, 0, &reason);
|
|
||||||
if(!kkey) {
|
if(!kkey) {
|
||||||
log_err("out of memory: verifying prime DS");
|
log_err("out of memory: verifying prime TA");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if(key_entry_isgood(kkey))
|
if(key_entry_isgood(kkey))
|
||||||
|
|
@ -2273,22 +2273,6 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
|
||||||
sec = sec_status_bogus;
|
sec = sec_status_bogus;
|
||||||
verbose(VERB_DETAIL, "validate keys with anchor(DS): %s",
|
verbose(VERB_DETAIL, "validate keys with anchor(DS): %s",
|
||||||
sec_status_to_string(sec));
|
sec_status_to_string(sec));
|
||||||
}
|
|
||||||
if(sec != sec_status_secure && ta->dnskey_rrset) {
|
|
||||||
sec = val_verify_rrset(qstate->env, ve, dnskey_rrset,
|
|
||||||
ta->dnskey_rrset, 0, &reason);
|
|
||||||
verbose(VERB_DETAIL, "validate keys with anchor(DNSKEY): %s",
|
|
||||||
sec_status_to_string(sec));
|
|
||||||
if(sec == sec_status_secure) {
|
|
||||||
kkey = key_entry_create_rrset(qstate->region,
|
|
||||||
ta->name, ta->namelen, ta->dclass,
|
|
||||||
dnskey_rrset, *qstate->env->now);
|
|
||||||
if(!kkey) {
|
|
||||||
log_err("out of memory: allocate primed key");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(sec != sec_status_secure) {
|
if(sec != sec_status_secure) {
|
||||||
log_nametypeclass(VERB_OPS, "failed to prime trust anchor -- "
|
log_nametypeclass(VERB_OPS, "failed to prime trust anchor -- "
|
||||||
|
|
@ -2390,7 +2374,7 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
|
||||||
log_query_info(VERB_DETAIL, "validated DS", qinfo);
|
log_query_info(VERB_DETAIL, "validated DS", qinfo);
|
||||||
*ke = key_entry_create_rrset(qstate->region,
|
*ke = key_entry_create_rrset(qstate->region,
|
||||||
qinfo->qname, qinfo->qname_len, qinfo->qclass, ds,
|
qinfo->qname, qinfo->qname_len, qinfo->qclass, ds,
|
||||||
*qstate->env->now);
|
NULL, *qstate->env->now);
|
||||||
return (*ke) != NULL;
|
return (*ke) != NULL;
|
||||||
} else if(subtype == VAL_CLASS_NODATA ||
|
} else if(subtype == VAL_CLASS_NODATA ||
|
||||||
subtype == VAL_CLASS_NAMEERROR) {
|
subtype == VAL_CLASS_NAMEERROR) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue