mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
ds2ke and nsec work.
git-svn-id: file:///svn/unbound/trunk@529 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
9ddbb430ef
commit
cedeaa8316
13 changed files with 580 additions and 14 deletions
|
|
@ -1,3 +1,8 @@
|
||||||
|
17 August 2007: Wouter
|
||||||
|
- work on DS2KE routine.
|
||||||
|
- val_nsec.c for validator NSEC proofs.
|
||||||
|
- unit test for NSEC bitmap reading.
|
||||||
|
|
||||||
16 August 2007: Wouter
|
16 August 2007: Wouter
|
||||||
- DS sig unit test.
|
- DS sig unit test.
|
||||||
- latest release libevent 1.3c and 1.3d have threading fixed.
|
- latest release libevent 1.3c and 1.3d have threading fixed.
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
#include "testcode/unitmain.h"
|
#include "testcode/unitmain.h"
|
||||||
#include "validator/val_sigcrypt.h"
|
#include "validator/val_sigcrypt.h"
|
||||||
|
#include "validator/val_nsec.h"
|
||||||
#include "validator/validator.h"
|
#include "validator/validator.h"
|
||||||
#include "testcode/ldns-testpkts.h"
|
#include "testcode/ldns-testpkts.h"
|
||||||
#include "util/data/msgreply.h"
|
#include "util/data/msgreply.h"
|
||||||
|
|
@ -312,10 +313,53 @@ dstest_file(const char* fname)
|
||||||
ldns_buffer_free(buf);
|
ldns_buffer_free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Test NSEC type bitmap routine */
|
||||||
|
static void
|
||||||
|
nsectest()
|
||||||
|
{
|
||||||
|
/* bitmap starts at type bitmap rdata field */
|
||||||
|
/* from rfc 4034 example */
|
||||||
|
char* bitmap = "\000\006\100\001\000\000\000\003"
|
||||||
|
"\004\033\000\000\000\000\000\000"
|
||||||
|
"\000\000\000\000\000\000\000\000"
|
||||||
|
"\000\000\000\000\000\000\000\000"
|
||||||
|
"\000\000\000\000\040";
|
||||||
|
size_t len = 37;
|
||||||
|
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 0));
|
||||||
|
unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_A));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 2));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 3));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 4));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 5));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 6));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 7));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 8));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 9));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 10));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 11));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 12));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 13));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 14));
|
||||||
|
unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_MX));
|
||||||
|
unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_RRSIG));
|
||||||
|
unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_NSEC));
|
||||||
|
unit_assert(unitest_nsec_has_type_rdata(bitmap, len, 1234));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1233));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1235));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1236));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1237));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1238));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1239));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1240));
|
||||||
|
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 2230));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
verify_test()
|
verify_test()
|
||||||
{
|
{
|
||||||
printf("verify test\n");
|
printf("verify test\n");
|
||||||
verifytest_file("testdata/test_signatures.1", "20070818005004");
|
verifytest_file("testdata/test_signatures.1", "20070818005004");
|
||||||
dstest_file("testdata/test_ds_sig.1");
|
dstest_file("testdata/test_ds_sig.1");
|
||||||
|
nsectest();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -686,6 +686,22 @@ struct ub_packed_rrset_key* reply_find_rrset_section_an(struct reply_info* rep,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ub_packed_rrset_key* reply_find_rrset_section_ns(struct reply_info* rep,
|
||||||
|
uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for(i=rep->an_numrrsets; i<rep->an_numrrsets+rep->ns_numrrsets; i++) {
|
||||||
|
struct ub_packed_rrset_key* s = rep->rrsets[i];
|
||||||
|
if(ntohs(s->rk.type) == type &&
|
||||||
|
ntohs(s->rk.rrset_class) == dclass &&
|
||||||
|
namelen == s->rk.dname_len &&
|
||||||
|
query_dname_compare(name, s->rk.dname) == 0) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep)
|
log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -333,6 +333,18 @@ struct ub_packed_rrset_key* reply_find_answer_rrset(struct query_info* qinfo,
|
||||||
struct ub_packed_rrset_key* reply_find_rrset_section_an(struct reply_info* rep,
|
struct ub_packed_rrset_key* reply_find_rrset_section_an(struct reply_info* rep,
|
||||||
uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass);
|
uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find rrset in reply, inside the authority section. Does not follow CNAMEs.
|
||||||
|
* @param rep: looks in authority section of this message.
|
||||||
|
* @param name: what to look for.
|
||||||
|
* @param namelen: length of name.
|
||||||
|
* @param type: looks for (host order).
|
||||||
|
* @param dclass: looks for (host order).
|
||||||
|
* @return: pointer to rrset, or NULL if not found.
|
||||||
|
*/
|
||||||
|
struct ub_packed_rrset_key* reply_find_rrset_section_ns(struct reply_info* rep,
|
||||||
|
uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Debug send the query info and reply info to the log in readable form.
|
* Debug send the query info and reply info to the log in readable form.
|
||||||
* @param str: descriptive string printed with packet content.
|
* @param str: descriptive string printed with packet content.
|
||||||
|
|
|
||||||
|
|
@ -257,3 +257,11 @@ sec_status_to_string(enum sec_status s)
|
||||||
}
|
}
|
||||||
return "unknown_sec_status_value";
|
return "unknown_sec_status_value";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
ub_packed_rrset_ttl(struct ub_packed_rrset_key* key)
|
||||||
|
{
|
||||||
|
struct packed_rrset_data* d = (struct packed_rrset_data*)key->
|
||||||
|
entry.data;
|
||||||
|
return d->ttl;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -265,6 +265,13 @@ void ub_packed_rrset_parsedelete(struct ub_packed_rrset_key* pkey,
|
||||||
*/
|
*/
|
||||||
size_t packed_rrset_sizeof(struct packed_rrset_data* data);
|
size_t packed_rrset_sizeof(struct packed_rrset_data* data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get TTL of rrset. RRset data must be filled in correctly.
|
||||||
|
* @param key: rrset key, with data to examine.
|
||||||
|
* @return ttl value.
|
||||||
|
*/
|
||||||
|
uint32_t ub_packed_rrset_ttl(struct ub_packed_rrset_key* key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate memory size of rrset entry. For hash table usage.
|
* Calculate memory size of rrset entry. For hash table usage.
|
||||||
* @param key: struct ub_packed_rrset_key*.
|
* @param key: struct ub_packed_rrset_key*.
|
||||||
|
|
|
||||||
|
|
@ -230,7 +230,7 @@ key_entry_create_null(struct region* region,
|
||||||
struct key_entry_data* d;
|
struct key_entry_data* d;
|
||||||
if(!key_entry_setup(region, name, namelen, dclass, &k, &d))
|
if(!key_entry_setup(region, name, namelen, dclass, &k, &d))
|
||||||
return NULL;
|
return NULL;
|
||||||
d->ttl = ttl;
|
d->ttl = time(0) + ttl;
|
||||||
d->isbad = 0;
|
d->isbad = 0;
|
||||||
d->rrset_type = LDNS_RR_TYPE_DNSKEY;
|
d->rrset_type = LDNS_RR_TYPE_DNSKEY;
|
||||||
d->rrset_data = NULL;
|
d->rrset_data = NULL;
|
||||||
|
|
@ -274,3 +274,31 @@ key_entry_create_bad(struct region* region,
|
||||||
d->rrset_data = NULL;
|
d->rrset_data = NULL;
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ub_packed_rrset_key*
|
||||||
|
key_entry_get_rrset(struct key_entry_key* kkey, struct region* region)
|
||||||
|
{
|
||||||
|
struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
|
||||||
|
struct ub_packed_rrset_key* rrk;
|
||||||
|
struct packed_rrset_data* rrd;
|
||||||
|
if(!d || !d->rrset_data)
|
||||||
|
return NULL;
|
||||||
|
rrk = region_alloc(region, sizeof(*rrk));
|
||||||
|
if(!rrk)
|
||||||
|
return NULL;
|
||||||
|
memset(rrk, 0, sizeof(*rrk));
|
||||||
|
rrk->rk.dname = region_alloc_init(region, kkey->name, kkey->namelen);
|
||||||
|
if(!rrk->rk.dname)
|
||||||
|
return NULL;
|
||||||
|
rrk->rk.dname_len = kkey->namelen;
|
||||||
|
rrk->rk.type = htons(d->rrset_type);
|
||||||
|
rrk->rk.rrset_class = htons(kkey->key_class);
|
||||||
|
rrk->entry.key = rrk;
|
||||||
|
rrd = region_alloc_init(region, d->rrset_data,
|
||||||
|
packed_rrset_sizeof(d->rrset_data));
|
||||||
|
if(!rrd)
|
||||||
|
return NULL;
|
||||||
|
rrk->entry.data = rrd;
|
||||||
|
packed_rrset_ptr_fixup(rrd);
|
||||||
|
return rrk;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ struct key_entry_data {
|
||||||
uint32_t ttl;
|
uint32_t ttl;
|
||||||
/** the key rrdata. can be NULL to signal keyless name. */
|
/** the key rrdata. can be NULL to signal keyless name. */
|
||||||
struct packed_rrset_data* rrset_data;
|
struct packed_rrset_data* rrset_data;
|
||||||
/** DNS RR type of the rrset data */
|
/** 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 */
|
||||||
uint8_t isbad;
|
uint8_t isbad;
|
||||||
|
|
@ -143,8 +143,8 @@ int key_entry_isbad(struct key_entry_key* kkey);
|
||||||
* @param region: where to allocate
|
* @param region: where to allocate
|
||||||
* @param name: the key name
|
* @param name: the key name
|
||||||
* @param namelen: length of name
|
* @param namelen: length of name
|
||||||
* @param dclass: class of key entry.
|
* @param dclass: class of key entry. (host order);
|
||||||
* @param ttl: what ttl should the key have.
|
* @param ttl: what ttl should the key have. relative.
|
||||||
* @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_null(struct region* region,
|
struct key_entry_key* key_entry_create_null(struct region* region,
|
||||||
|
|
@ -155,7 +155,7 @@ struct key_entry_key* key_entry_create_null(struct region* region,
|
||||||
* @param region: where to allocate.
|
* @param region: where to allocate.
|
||||||
* @param name: the key name
|
* @param name: the key name
|
||||||
* @param namelen: length of name
|
* @param namelen: length of name
|
||||||
* @param dclass: class of key entry.
|
* @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.
|
||||||
* @return new key entry or NULL on alloc failure
|
* @return new key entry or NULL on alloc failure
|
||||||
*/
|
*/
|
||||||
|
|
@ -168,10 +168,19 @@ struct key_entry_key* key_entry_create_rrset(struct region* region,
|
||||||
* @param region: where to allocate
|
* @param region: where to allocate
|
||||||
* @param name: the key name
|
* @param name: the key name
|
||||||
* @param namelen: length of name
|
* @param namelen: length of name
|
||||||
* @param dclass: class of key entry.
|
* @param dclass: class of key entry. (host order);
|
||||||
* @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_bad(struct region* region,
|
struct key_entry_key* key_entry_create_bad(struct region* region,
|
||||||
uint8_t* name, size_t namelen, uint16_t dclass);
|
uint8_t* name, size_t namelen, uint16_t dclass);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain rrset from a key entry, allocated in region.
|
||||||
|
* @param kkey: key entry to convert to a rrset.
|
||||||
|
* @param region: where to allocate rrset
|
||||||
|
* @return rrset copy; if no rrset or alloc error returns NULL.
|
||||||
|
*/
|
||||||
|
struct ub_packed_rrset_key* key_entry_get_rrset(struct key_entry_key* kkey,
|
||||||
|
struct region* region);
|
||||||
|
|
||||||
#endif /* VALIDATOR_VAL_KENTRY_H */
|
#endif /* VALIDATOR_VAL_KENTRY_H */
|
||||||
|
|
|
||||||
178
validator/val_nsec.c
Normal file
178
validator/val_nsec.c
Normal file
|
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
* validator/val_nsec.c - validator NSEC denial of existance functions.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007, NLnet Labs. All rights reserved.
|
||||||
|
*
|
||||||
|
* This software is open source.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||||
|
* be used to endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
*
|
||||||
|
* This file contains helper functions for the validator module.
|
||||||
|
* The functions help with NSEC checking, the different NSEC proofs
|
||||||
|
* for denial of existance, and proofs for presence of types.
|
||||||
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
#include "validator/val_nsec.h"
|
||||||
|
#include "validator/val_utils.h"
|
||||||
|
#include "util/data/msgreply.h"
|
||||||
|
#include "util/data/dname.h"
|
||||||
|
|
||||||
|
/** Check type present in NSEC typemap with bitmap arg */
|
||||||
|
static int
|
||||||
|
nsec_has_type_rdata(uint8_t* bitmap, size_t len, uint16_t type)
|
||||||
|
{
|
||||||
|
/* bitmasks for determining type-lowerbits presence */
|
||||||
|
uint8_t masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
|
||||||
|
uint8_t type_window = type>>8;
|
||||||
|
uint8_t type_low = type&0xff;
|
||||||
|
uint8_t win, winlen;
|
||||||
|
/* read each of the type bitmap windows and see if the searched
|
||||||
|
* type is amongst it */
|
||||||
|
while(len > 0) {
|
||||||
|
if(len < 3) /* bad window, at least window# winlen bitmap */
|
||||||
|
return 0;
|
||||||
|
win = *bitmap++;
|
||||||
|
winlen = *bitmap++;
|
||||||
|
len -= 2;
|
||||||
|
if(len < winlen || winlen < 1 || winlen > 32)
|
||||||
|
return 0; /* bad window length */
|
||||||
|
if(win == type_window) {
|
||||||
|
/* search window bitmap for the correct byte */
|
||||||
|
/* mybyte is 0 if we need the first byte */
|
||||||
|
size_t mybyte = type_low>>3;
|
||||||
|
if(winlen <= mybyte)
|
||||||
|
return 0; /* window too short */
|
||||||
|
return bitmap[mybyte] & masks[type_low&0x7];
|
||||||
|
} else {
|
||||||
|
/* not the window we are looking for */
|
||||||
|
bitmap += winlen;
|
||||||
|
len -= winlen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* end of bitmap reached, no type found */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
unitest_nsec_has_type_rdata(char* bitmap, size_t len, uint16_t type)
|
||||||
|
{
|
||||||
|
return nsec_has_type_rdata((uint8_t*)bitmap, len, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if type is present in the NSEC typemap
|
||||||
|
* @param nsec: the nsec RRset.
|
||||||
|
* If there are multiple RRs, then each must have the same typemap,
|
||||||
|
* since the typemap represents the types at this domain node.
|
||||||
|
* @param type: type to check for, host order.
|
||||||
|
* @return true if present
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
nsec_has_type(struct ub_packed_rrset_key* nsec, uint16_t type)
|
||||||
|
{
|
||||||
|
struct packed_rrset_data* d = (struct packed_rrset_data*)nsec->
|
||||||
|
entry.data;
|
||||||
|
size_t len;
|
||||||
|
if(!d || d->count == 0 || d->rr_len[0] < 2+1)
|
||||||
|
return 0;
|
||||||
|
len = dname_valid(d->rr_data[0]+2, d->rr_len[0]-2);
|
||||||
|
if(!len)
|
||||||
|
return 0;
|
||||||
|
nsec_has_type_rdata(d->rr_data[0]+2+len, d->rr_len[0]-2-len, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For an NSEC that matches the DS queried for, check absence of DS type.
|
||||||
|
*
|
||||||
|
* @param nsec: NSEC for proof, must be trusted.
|
||||||
|
* @param qinfo: what is queried for.
|
||||||
|
* @return if secure the nsec proves that no DS is present, or
|
||||||
|
* insecure if it proves it is not a delegation point.
|
||||||
|
* or bogus if something was wrong.
|
||||||
|
*/
|
||||||
|
enum sec_status
|
||||||
|
val_nsec_proves_no_ds(struct ub_packed_rrset_key* nsec,
|
||||||
|
struct query_info* qinfo)
|
||||||
|
{
|
||||||
|
log_assert(qinfo->qtype == LDNS_RR_TYPE_DS);
|
||||||
|
log_assert(ntohs(nsec->rk.type) == LDNS_RR_TYPE_NSEC);
|
||||||
|
/* this proof may also work if qname is a subdomain */
|
||||||
|
log_assert(query_dname_compare(nsec->rk.dname, qinfo->qname) == 0);
|
||||||
|
|
||||||
|
return sec_status_bogus;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum sec_status
|
||||||
|
val_nsec_prove_nodata_ds(struct module_env* env, struct val_env* ve,
|
||||||
|
struct query_info* qinfo, struct reply_info* rep,
|
||||||
|
struct key_entry_key* kkey, uint32_t* proof_ttl)
|
||||||
|
{
|
||||||
|
struct ub_packed_rrset_key* nsec = reply_find_rrset_section_ns(
|
||||||
|
rep, qinfo->qname, qinfo->qname_len, LDNS_RR_TYPE_NSEC,
|
||||||
|
qinfo->qclass);
|
||||||
|
|
||||||
|
/* If we have a NSEC at the same name, it must prove one
|
||||||
|
* of two things
|
||||||
|
* --
|
||||||
|
* 1) this is a delegation point and there is no DS
|
||||||
|
* 2) this is not a delegation point */
|
||||||
|
if(nsec) {
|
||||||
|
enum sec_status sec = val_verify_rrset_entry(env, ve, nsec,
|
||||||
|
kkey);
|
||||||
|
if(sec != sec_status_secure) {
|
||||||
|
verbose(VERB_ALGO, "NSEC RRset for the "
|
||||||
|
"referral did not verify.");
|
||||||
|
return sec_status_bogus;
|
||||||
|
}
|
||||||
|
sec = val_nsec_proves_no_ds(nsec, qinfo);
|
||||||
|
if(sec == sec_status_bogus) {
|
||||||
|
/* something was wrong. */
|
||||||
|
return sec;
|
||||||
|
} else if(sec == sec_status_insecure) {
|
||||||
|
/* this wasn't a delegation point. */
|
||||||
|
return sec;
|
||||||
|
} else if(sec == sec_status_secure) {
|
||||||
|
/* this proved no DS. */
|
||||||
|
*proof_ttl = ub_packed_rrset_ttl(nsec);
|
||||||
|
return sec;
|
||||||
|
}
|
||||||
|
/* if unchecked, fall through to next proof */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, there is no NSEC at qname. This could be an ENT.
|
||||||
|
* (ENT=empty non terminal). If not, this is broken. */
|
||||||
|
|
||||||
|
/* verify NSEC rrsets in auth section, call */
|
||||||
|
/* ValUtils.nsecProvesNodata, if so: NULL entry */
|
||||||
|
|
||||||
|
return sec_status_bogus;
|
||||||
|
}
|
||||||
80
validator/val_nsec.h
Normal file
80
validator/val_nsec.h
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* validator/val_nsec.h - validator NSEC denial of existance functions.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007, NLnet Labs. All rights reserved.
|
||||||
|
*
|
||||||
|
* This software is open source.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||||
|
* be used to endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
*
|
||||||
|
* This file contains helper functions for the validator module.
|
||||||
|
* The functions help with NSEC checking, the different NSEC proofs
|
||||||
|
* for denial of existance, and proofs for presence of types.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VALIDATOR_VAL_NSEC_H
|
||||||
|
#define VALIDATOR_VAL_NSEC_H
|
||||||
|
struct val_env;
|
||||||
|
struct module_env;
|
||||||
|
struct ub_packed_rrset_key;
|
||||||
|
enum sec_status;
|
||||||
|
struct reply_info;
|
||||||
|
struct query_info;
|
||||||
|
struct key_entry_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check DS absence.
|
||||||
|
* There is a NODATA reply to a DS that needs checking.
|
||||||
|
* NSECs can prove this is not a delegation point, or sucessfully prove
|
||||||
|
* that there is no DS. Or this fails.
|
||||||
|
*
|
||||||
|
* @param env: module env for rrsig verification routines.
|
||||||
|
* @param ve: validator env for rrsig verification routines.
|
||||||
|
* @param qinfo: the DS queried for.
|
||||||
|
* @param rep: reply received.
|
||||||
|
* @param kkey: key entry to use for verification of signatures.
|
||||||
|
* @param proof_ttl: if secure, the TTL of how long this proof lasts.
|
||||||
|
* @return security status.
|
||||||
|
* SECURE: proved absence of DS.
|
||||||
|
* INSECURE: proved that this was not a delegation point.
|
||||||
|
* BOGUS: crypto bad, or no absence of DS proven.
|
||||||
|
* UNCHECKED: there was no way to prove anything (no nsecs, unknown algo).
|
||||||
|
*/
|
||||||
|
enum sec_status val_nsec_prove_nodata_ds(struct module_env* env,
|
||||||
|
struct val_env* ve, struct query_info* qinfo,
|
||||||
|
struct reply_info* rep, struct key_entry_key* kkey,
|
||||||
|
uint32_t* proof_ttl);
|
||||||
|
|
||||||
|
/** Unit test call to test function for nsec typemap check */
|
||||||
|
int unitest_nsec_has_type_rdata(char* bitmap, size_t len, uint16_t type);
|
||||||
|
|
||||||
|
#endif /* VALIDATOR_VAL_NSEC_H */
|
||||||
|
|
@ -210,6 +210,25 @@ val_verify_rrset(struct module_env* env, struct val_env* ve,
|
||||||
return sec;
|
return sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
/* temporary dnskey rrset-key */
|
||||||
|
struct ub_packed_rrset_key dnskey;
|
||||||
|
struct key_entry_data* kd = (struct key_entry_data*)kkey->entry.data;
|
||||||
|
enum sec_status sec;
|
||||||
|
dnskey.rk.type = htons(kd->rrset_type);
|
||||||
|
dnskey.rk.rrset_class = htons(kkey->key_class);
|
||||||
|
dnskey.rk.flags = 0;
|
||||||
|
dnskey.rk.dname = kkey->name;
|
||||||
|
dnskey.rk.dname_len = kkey->namelen;
|
||||||
|
dnskey.entry.key = &dnskey;
|
||||||
|
dnskey.entry.data = kd->rrset_data;
|
||||||
|
sec = val_verify_rrset(env, ve, rrset, &dnskey);
|
||||||
|
return sec;
|
||||||
|
}
|
||||||
|
|
||||||
/** verify that a DS RR hashes to a key and that key signs the set */
|
/** verify that a DS RR hashes to a key and that key signs the set */
|
||||||
static enum sec_status
|
static enum sec_status
|
||||||
verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve,
|
verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve,
|
||||||
|
|
@ -312,3 +331,15 @@ val_verify_new_DNSKEYs(struct region* region, struct module_env* env,
|
||||||
return key_entry_create_bad(region, ds_rrset->rk.dname,
|
return key_entry_create_bad(region, ds_rrset->rk.dname,
|
||||||
ds_rrset->rk.dname_len, ntohs(ds_rrset->rk.rrset_class));
|
ds_rrset->rk.dname_len, ntohs(ds_rrset->rk.rrset_class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
val_dsset_isusable(struct ub_packed_rrset_key* ds_rrset)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for(i=0; i<rrset_get_count(ds_rrset); i++) {
|
||||||
|
if(ds_digest_algo_is_supported(ds_rrset, i) &&
|
||||||
|
ds_key_algo_is_supported(ds_rrset, i))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ struct reply_info;
|
||||||
struct val_env;
|
struct val_env;
|
||||||
struct module_env;
|
struct module_env;
|
||||||
struct ub_packed_rrset_key;
|
struct ub_packed_rrset_key;
|
||||||
|
struct key_entry_key;
|
||||||
struct region;
|
struct region;
|
||||||
enum sec_status;
|
enum sec_status;
|
||||||
|
|
||||||
|
|
@ -103,6 +104,18 @@ void val_find_signer(struct query_info* qinf, struct reply_info* rep,
|
||||||
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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify RRset with keys from a keyset.
|
||||||
|
* @param env: module environment (scratch buffer)
|
||||||
|
* @param ve: validator environment (verification settings)
|
||||||
|
* @param rrset: what to verify
|
||||||
|
* @param kkey: key_entry to verify with.
|
||||||
|
* @return security status of verification.
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
* match the DNSKEY keys.
|
* match the DNSKEY keys.
|
||||||
|
|
@ -127,4 +140,14 @@ struct key_entry_key* val_verify_new_DNSKEYs(struct region* region,
|
||||||
struct ub_packed_rrset_key* dnskey_rrset,
|
struct ub_packed_rrset_key* dnskey_rrset,
|
||||||
struct ub_packed_rrset_key* ds_rrset);
|
struct ub_packed_rrset_key* ds_rrset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if DS rrset is usable for validator or not.
|
||||||
|
* Returns true if the algorithms for key and DShash are supported,
|
||||||
|
* for at least one RR.
|
||||||
|
*
|
||||||
|
* @param ds_rrset: the newly received DS rrset.
|
||||||
|
* @return true or false if not usable.
|
||||||
|
*/
|
||||||
|
int val_dsset_isusable(struct ub_packed_rrset_key* ds_rrset);
|
||||||
|
|
||||||
#endif /* VALIDATOR_VAL_UTILS_H */
|
#endif /* VALIDATOR_VAL_UTILS_H */
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@
|
||||||
#include "validator/val_kcache.h"
|
#include "validator/val_kcache.h"
|
||||||
#include "validator/val_kentry.h"
|
#include "validator/val_kentry.h"
|
||||||
#include "validator/val_utils.h"
|
#include "validator/val_utils.h"
|
||||||
|
#include "validator/val_nsec.h"
|
||||||
#include "services/cache/dns.h"
|
#include "services/cache/dns.h"
|
||||||
#include "util/data/dname.h"
|
#include "util/data/dname.h"
|
||||||
#include "util/module.h"
|
#include "util/module.h"
|
||||||
|
|
@ -557,7 +558,7 @@ primeResponseToKE(int rcode, struct dns_msg* msg, struct trust_anchor* ta,
|
||||||
log_query_info(VERB_ALGO, "failed to prime trust anchor -- "
|
log_query_info(VERB_ALGO, "failed to prime trust anchor -- "
|
||||||
"could not fetch DNSKEY rrset", &msg->qinfo);
|
"could not fetch DNSKEY rrset", &msg->qinfo);
|
||||||
kkey = key_entry_create_null(qstate->region, ta->name,
|
kkey = key_entry_create_null(qstate->region, ta->name,
|
||||||
ta->namelen, ta->dclass, time(0)+NULL_KEY_TTL);
|
ta->namelen, ta->dclass, NULL_KEY_TTL);
|
||||||
if(!kkey) {
|
if(!kkey) {
|
||||||
log_err("out of memory: allocate null prime key");
|
log_err("out of memory: allocate null prime key");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -599,7 +600,7 @@ primeResponseToKE(int rcode, struct dns_msg* msg, struct trust_anchor* ta,
|
||||||
/* NOTE: in this case, we should probably reject the trust
|
/* NOTE: in this case, we should probably reject the trust
|
||||||
* anchor for longer, perhaps forever. */
|
* anchor for longer, perhaps forever. */
|
||||||
kkey = key_entry_create_null(qstate->region, ta->name,
|
kkey = key_entry_create_null(qstate->region, ta->name,
|
||||||
ta->namelen, ta->dclass, time(0)+NULL_KEY_TTL);
|
ta->namelen, ta->dclass, NULL_KEY_TTL);
|
||||||
if(!kkey) {
|
if(!kkey) {
|
||||||
log_err("out of memory: allocate null prime key");
|
log_err("out of memory: allocate null prime key");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -615,8 +616,132 @@ primeResponseToKE(int rcode, struct dns_msg* msg, struct trust_anchor* ta,
|
||||||
return kkey;
|
return kkey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In inform supers, with the resulting message and rcode and the current
|
||||||
|
* keyset in the super state, validate the DS response, returning a KeyEntry.
|
||||||
|
*
|
||||||
|
* @param qstate: query state that is validating and asked for a DS.
|
||||||
|
* @param vq: validator query state
|
||||||
|
* @param id: module id.
|
||||||
|
* @param rcode: rcode result value.
|
||||||
|
* @param msg: result message (if rcode is OK).
|
||||||
|
* @param qinfo: from the sub query state, query info.
|
||||||
|
* @param ke: the key entry to return. It returns
|
||||||
|
* bad if the DS response fails to validate, null if the
|
||||||
|
* DS response indicated an end to secure space, good if the DS
|
||||||
|
* validated. It returns null if the DS response indicated that the
|
||||||
|
* request wasn't a delegation point.
|
||||||
|
* @return 0 on servfail error (malloc failure).
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
|
||||||
|
int id, int rcode, struct dns_msg* msg, struct query_info* qinfo,
|
||||||
|
struct key_entry_key** ke)
|
||||||
|
{
|
||||||
|
struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
|
||||||
|
enum val_classification subtype;
|
||||||
|
if(rcode != LDNS_RCODE_NOERROR) {
|
||||||
|
/* errors here pretty much break validation */
|
||||||
|
verbose(VERB_ALGO, "DS response was error, thus bogus");
|
||||||
|
goto return_bogus;
|
||||||
|
}
|
||||||
|
|
||||||
|
subtype = val_classify_response(qinfo, msg->rep);
|
||||||
|
if(subtype == VAL_CLASS_POSITIVE) {
|
||||||
|
struct ub_packed_rrset_key* ds;
|
||||||
|
enum sec_status sec;
|
||||||
|
ds = reply_find_answer_rrset(qinfo, msg->rep);
|
||||||
|
/* If there was no DS rrset, then we have mis-classified
|
||||||
|
* this message. */
|
||||||
|
if(!ds) {
|
||||||
|
log_warn("internal error: POSITIVE DS response was "
|
||||||
|
"missing DS.");
|
||||||
|
goto return_bogus;
|
||||||
|
}
|
||||||
|
/* Verify only returns BOGUS or SECURE. If the rrset is
|
||||||
|
* bogus, then we are done. */
|
||||||
|
sec = val_verify_rrset_entry(qstate->env, ve, ds,
|
||||||
|
vq->key_entry);
|
||||||
|
if(sec != sec_status_secure) {
|
||||||
|
verbose(VERB_ALGO, "DS rrset in DS response did "
|
||||||
|
"not verify");
|
||||||
|
goto return_bogus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the DS rrset validates, we still have to make sure
|
||||||
|
* that they are usable. */
|
||||||
|
if(!val_dsset_isusable(ds)) {
|
||||||
|
/* If they aren't usable, then we treat it like
|
||||||
|
* there was no DS. */
|
||||||
|
*ke = key_entry_create_null(qstate->region,
|
||||||
|
qinfo->qname, qinfo->qname_len, qinfo->qclass,
|
||||||
|
ub_packed_rrset_ttl(ds));
|
||||||
|
return (*ke) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, we return the positive response. */
|
||||||
|
log_query_info(VERB_ALGO, "DS rrset was good.", qinfo);
|
||||||
|
*ke = key_entry_create_rrset(qstate->region,
|
||||||
|
qinfo->qname, qinfo->qname_len, qinfo->qclass, ds);
|
||||||
|
return (*ke) != NULL;
|
||||||
|
} else if(subtype == VAL_CLASS_NODATA) {
|
||||||
|
/* NODATA means that the qname exists, but that there was
|
||||||
|
* no DS. This is a pretty normal case. */
|
||||||
|
uint32_t proof_ttl = 0;
|
||||||
|
|
||||||
|
/* Try to prove absence of the DS with NSEC */
|
||||||
|
enum sec_status sec = val_nsec_prove_nodata_ds(qstate->env, ve,
|
||||||
|
qinfo, msg->rep, vq->key_entry, &proof_ttl);
|
||||||
|
switch(sec) {
|
||||||
|
case sec_status_secure:
|
||||||
|
verbose(VERB_ALGO, "NSEC RRset for the "
|
||||||
|
"referral proved no DS.");
|
||||||
|
*ke = key_entry_create_null(qstate->region,
|
||||||
|
qinfo->qname, qinfo->qname_len,
|
||||||
|
qinfo->qclass, proof_ttl);
|
||||||
|
return (*ke) != NULL;
|
||||||
|
case sec_status_insecure:
|
||||||
|
verbose(VERB_ALGO, "NSEC RRset for the "
|
||||||
|
"referral proved not a delegation point");
|
||||||
|
*ke = NULL;
|
||||||
|
return 1;
|
||||||
|
case sec_status_bogus:
|
||||||
|
verbose(VERB_ALGO, "NSEC RRset for the "
|
||||||
|
"referral did not prove no DS.");
|
||||||
|
goto return_bogus;
|
||||||
|
case sec_status_unchecked:
|
||||||
|
default:
|
||||||
|
/* NSEC proof did not work, try next */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Or it could be using NSEC3. TODO */
|
||||||
|
|
||||||
|
/* Apparently, no available NSEC/NSEC3 proved NODATA, so
|
||||||
|
* this is BOGUS. */
|
||||||
|
verbose(VERB_ALGO, "DS ran out of options, so return bogus");
|
||||||
|
goto return_bogus;
|
||||||
|
} else if(subtype == VAL_CLASS_NAMEERROR) {
|
||||||
|
verbose(VERB_ALGO, "DS response was NAMEERROR, thus bogus.");
|
||||||
|
goto return_bogus;
|
||||||
|
} else {
|
||||||
|
verbose(VERB_ALGO, "Encountered an unhandled type of "
|
||||||
|
"DS response, thus bogus.");
|
||||||
|
return_bogus:
|
||||||
|
*ke = key_entry_create_bad(qstate->region, qinfo->qname,
|
||||||
|
qinfo->qname_len, qinfo->qclass);
|
||||||
|
return (*ke) != NULL;
|
||||||
|
}
|
||||||
|
/* unreachable */
|
||||||
|
log_assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process DS response. Called from inform_supers.
|
* Process DS response. Called from inform_supers.
|
||||||
|
* Because it is in inform_supers, the mesh itself is busy doing callbacks
|
||||||
|
* for a state that is to be deleted soon; don't touch the mesh; instead
|
||||||
|
* set a state in the super, as the super will be reactivated soon.
|
||||||
|
* Perform processing to determine what state to set in the super.
|
||||||
*
|
*
|
||||||
* @param qstate: query state that is validating and asked for a DS.
|
* @param qstate: query state that is validating and asked for a DS.
|
||||||
* @param vq: validator query state
|
* @param vq: validator query state
|
||||||
|
|
@ -630,9 +755,7 @@ process_ds_response(struct module_qstate* qstate, struct val_qstate* vq,
|
||||||
int id, int rcode, struct dns_msg* msg, struct query_info* qinfo)
|
int id, int rcode, struct dns_msg* msg, struct query_info* qinfo)
|
||||||
{
|
{
|
||||||
struct key_entry_key* dske = NULL;
|
struct key_entry_key* dske = NULL;
|
||||||
/* TODO
|
if(!ds_response_to_ke(qstate, vq, id, rcode, msg, qinfo, &dske)) {
|
||||||
if(!ds_response_to_ke(qstate, vq, id, rcode, msg, &dske)) {
|
|
||||||
@@@ */ if(0) {
|
|
||||||
log_err("malloc failure in DStoKE");
|
log_err("malloc failure in DStoKE");
|
||||||
vq->key_entry = NULL; /* make it error */
|
vq->key_entry = NULL; /* make it error */
|
||||||
vq->state = VAL_VALIDATE_STATE;
|
vq->state = VAL_VALIDATE_STATE;
|
||||||
|
|
@ -644,9 +767,7 @@ process_ds_response(struct module_qstate* qstate, struct val_qstate* vq,
|
||||||
/* ds response indicated that we aren't on a delegation point.
|
/* ds response indicated that we aren't on a delegation point.
|
||||||
* Keep the forState.state on FINDKEY. */
|
* Keep the forState.state on FINDKEY. */
|
||||||
} else if(key_entry_isgood(dske)) {
|
} else if(key_entry_isgood(dske)) {
|
||||||
/* TODO
|
vq->ds_rrset = key_entry_get_rrset(dske, qstate->region);
|
||||||
vq->ds_rrset = key_entry_getrrset(dske);
|
|
||||||
*/
|
|
||||||
if(!vq->ds_rrset) {
|
if(!vq->ds_rrset) {
|
||||||
log_err("malloc failure in process DS");
|
log_err("malloc failure in process DS");
|
||||||
vq->key_entry = NULL; /* make it error */
|
vq->key_entry = NULL; /* make it error */
|
||||||
|
|
@ -667,6 +788,10 @@ process_ds_response(struct module_qstate* qstate, struct val_qstate* vq,
|
||||||
/**
|
/**
|
||||||
* Process DNSKEY response. Called from inform_supers.
|
* Process DNSKEY response. Called from inform_supers.
|
||||||
* Sets the key entry in the state.
|
* Sets the key entry in the state.
|
||||||
|
* Because it is in inform_supers, the mesh itself is busy doing callbacks
|
||||||
|
* for a state that is to be deleted soon; don't touch the mesh; instead
|
||||||
|
* set a state in the super, as the super will be reactivated soon.
|
||||||
|
* Perform processing to determine what state to set in the super.
|
||||||
*
|
*
|
||||||
* @param qstate: query state that is validating and asked for a DNSKEY.
|
* @param qstate: query state that is validating and asked for a DNSKEY.
|
||||||
* @param vq: validator query state
|
* @param vq: validator query state
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue