mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
key prime, DS test.
git-svn-id: file:///svn/unbound/trunk@525 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
f6371f11a4
commit
e4aa70b4c5
9 changed files with 149 additions and 8 deletions
|
|
@ -1,3 +1,10 @@
|
||||||
|
16 August 2007: Wouter
|
||||||
|
- DS sig unit test.
|
||||||
|
- latest release libevent 1.3c and 1.3d have threading fixed.
|
||||||
|
- key entry fixup data pointer and ttl absolute.
|
||||||
|
- This makes a key-prime succeed in validator, with DS or DNSKEY as
|
||||||
|
trust-anchor.
|
||||||
|
|
||||||
15 August 2007: Wouter
|
15 August 2007: Wouter
|
||||||
- crypto calls to verify signatures.
|
- crypto calls to verify signatures.
|
||||||
- unit test for rrsig verification.
|
- unit test for rrsig verification.
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ This software is under BSD license, see LICENSE for details.
|
||||||
|
|
||||||
Known issues
|
Known issues
|
||||||
------------
|
------------
|
||||||
o If libevent is older (1.3 and before), unbound will exit instead of reload
|
o If libevent is older (before 1.3c), unbound will exit instead of reload
|
||||||
on sighup. On a restart 'did not exit gracefully last time' warning is
|
on sighup. On a restart 'did not exit gracefully last time' warning is
|
||||||
printed. Perform ./configure --with-libevent=no or update libevent, rerun
|
printed. Perform ./configure --with-libevent=no or update libevent, rerun
|
||||||
configure and recompile unbound to make sighup work correctly.
|
configure and recompile unbound to make sighup work correctly.
|
||||||
|
|
|
||||||
|
|
@ -182,6 +182,59 @@ verifytest_entry(struct entry* e, struct alloc_cache* alloc, struct region*
|
||||||
query_info_clear(&qinfo);
|
query_info_clear(&qinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** find RRset in reply by type */
|
||||||
|
static struct ub_packed_rrset_key*
|
||||||
|
find_rrset_type(struct reply_info* rep, uint16_t type)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for(i=0; i<rep->rrset_count; i++) {
|
||||||
|
if(ntohs(rep->rrsets[i]->rk.type) == type)
|
||||||
|
return rep->rrsets[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** DS sig test an entry - get DNSKEY and DS in entry and verify */
|
||||||
|
static void
|
||||||
|
dstest_entry(struct entry* e, struct alloc_cache* alloc, struct region*
|
||||||
|
region, ldns_buffer* pkt, struct module_env* env)
|
||||||
|
{
|
||||||
|
struct query_info qinfo;
|
||||||
|
struct reply_info* rep = NULL;
|
||||||
|
struct ub_packed_rrset_key* ds, *dnskey;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
region_free_all(region);
|
||||||
|
if(vsig) {
|
||||||
|
printf("verifying DS-DNSKEY match:\n");
|
||||||
|
ldns_pkt_print(stdout, e->reply_list->reply);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep);
|
||||||
|
ds = find_rrset_type(rep, LDNS_RR_TYPE_DS);
|
||||||
|
dnskey = find_rrset_type(rep, LDNS_RR_TYPE_DNSKEY);
|
||||||
|
/* check test is OK */
|
||||||
|
unit_assert(ds && dnskey);
|
||||||
|
|
||||||
|
ret = ds_digest_match_dnskey(env, dnskey, 0, ds, 0);
|
||||||
|
if(strncmp((char*)qinfo.qname, "\003yes", 4) == 0) {
|
||||||
|
if(vsig) {
|
||||||
|
printf("result(yes)= %s\n", ret?"yes":"no");
|
||||||
|
}
|
||||||
|
unit_assert(ret);
|
||||||
|
} else if (strncmp((char*)qinfo.qname, "\002no", 3) == 0) {
|
||||||
|
if(vsig) {
|
||||||
|
printf("result(no)= %s\n", ret?"yes":"no");
|
||||||
|
}
|
||||||
|
unit_assert(!ret);
|
||||||
|
} else {
|
||||||
|
fatal_exit("Bad qname in DS unit test, yes or no");
|
||||||
|
}
|
||||||
|
|
||||||
|
reply_info_parsedelete(rep, alloc);
|
||||||
|
query_info_clear(&qinfo);
|
||||||
|
}
|
||||||
|
|
||||||
/** verify from a file */
|
/** verify from a file */
|
||||||
static void
|
static void
|
||||||
verifytest_file(const char* fname, const char* at_date)
|
verifytest_file(const char* fname, const char* at_date)
|
||||||
|
|
@ -224,9 +277,45 @@ verifytest_file(const char* fname, const char* at_date)
|
||||||
ldns_buffer_free(buf);
|
ldns_buffer_free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** verify DS matches DNSKEY from a file */
|
||||||
|
static void
|
||||||
|
dstest_file(const char* fname)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The file contains a list of ldns-testpkts entries.
|
||||||
|
* The first entry must be a query for DNSKEY.
|
||||||
|
* The answer rrset is the keyset that will be used for verification
|
||||||
|
*/
|
||||||
|
struct region* region = region_create(malloc, free);
|
||||||
|
struct alloc_cache alloc;
|
||||||
|
ldns_buffer* buf = ldns_buffer_new(65535);
|
||||||
|
struct entry* e;
|
||||||
|
struct entry* list = read_datafile(fname);
|
||||||
|
struct module_env env;
|
||||||
|
|
||||||
|
if(!list)
|
||||||
|
fatal_exit("could not read %s: %s", fname, strerror(errno));
|
||||||
|
alloc_init(&alloc, NULL, 1);
|
||||||
|
memset(&env, 0, sizeof(env));
|
||||||
|
env.scratch = region;
|
||||||
|
env.scratch_buffer = buf;
|
||||||
|
unit_assert(region && buf);
|
||||||
|
|
||||||
|
/* ready to go! */
|
||||||
|
for(e = list; e; e = e->next) {
|
||||||
|
dstest_entry(e, &alloc, region, buf, &env);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_entry(list);
|
||||||
|
region_destroy(region);
|
||||||
|
alloc_clear(&alloc);
|
||||||
|
ldns_buffer_free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
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");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
33
testdata/test_ds_sig.1
vendored
Normal file
33
testdata/test_ds_sig.1
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
;
|
||||||
|
; DS match test file.
|
||||||
|
; test matching of DS hash against DNSKEYs.
|
||||||
|
;
|
||||||
|
; enter ENTRYs with a DS and a DNSKEY.
|
||||||
|
; These are matched against another.
|
||||||
|
; If the query name starts with 'yes' then it must match.
|
||||||
|
; If the query name starts with 'no' then it must not match.
|
||||||
|
|
||||||
|
ENTRY_BEGIN
|
||||||
|
SECTION QUESTION
|
||||||
|
yes. IN A
|
||||||
|
SECTION ANSWER
|
||||||
|
nlnetlabs.nl. 3600 IN DS 43791 RSASHA1 1 81ee88356df3c3077549445ed2fb1c92adc80641
|
||||||
|
nlnetlabs.nl. DNSKEY 257 3 5 AQPzzTWMz8qSWIQlfRnPckx2BiVmkVN6LPupO3mbz7FhLSnm26n6iG9N Lby97Ji453aWZY3M5/xJBSOS2vWtco2t8C0+xeO1bc/d6ZTy32DHchpW 6rDH1vp86Ll+ha0tmwyy9QP7y2bVw5zSbFCrefk8qCUBgfHm9bHzMG1U BYtEIQ==
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
ENTRY_BEGIN
|
||||||
|
SECTION QUESTION
|
||||||
|
yes. IN A
|
||||||
|
SECTION ANSWER
|
||||||
|
jelte.nlnetlabs.nl. DS 42860 5 1 14D739EB566D2B1A5E216A0BA4D17FA9B038BE4A
|
||||||
|
jelte.nlnetlabs.nl. 3600 IN DNSKEY 256 3 5 AQOraLfzarHAlFskVGwAGnX0LRjlcOiO6y5WM4Kz+QvZ9vX28h4lOvnf d5tkxnZm7ERLTAJoFq+1w/wl7VXs2Isz75BSZ7LQh3OT2xXnS6VT5ZxX ko/UCOdoGiKZZ63jHZ0jNSTCYy8+5rfvwRD8s3gGuErp5KcHg3V8VLUK SDNNEQ==
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
ENTRY_BEGIN
|
||||||
|
SECTION QUESTION
|
||||||
|
no. IN A
|
||||||
|
SECTION ANSWER
|
||||||
|
nlnetlabs.nl. 3600 IN DS 43791 RSASHA1 1 14D739EB566D2B1A5E216A0BA4D17FA9B038BE4A
|
||||||
|
nlnetlabs.nl. DNSKEY 257 3 5 AQPzzTWMz8qSWIQlfRnPckx2BiVmkVN6LPupO3mbz7FhLSnm26n6iG9N Lby97Ji453aWZY3M5/xJBSOS2vWtco2t8C0+xeO1bc/d6ZTy32DHchpW 6rDH1vp86Ll+ha0tmwyy9QP7y2bVw5zSbFCrefk8qCUBgfHm9bHzMG1U BYtEIQ==
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
|
@ -190,7 +190,7 @@ log_hex(const char* msg, void* data, size_t length)
|
||||||
else {
|
else {
|
||||||
for(i=0; i<length*2; i+=blocksize) {
|
for(i=0; i<length*2; i+=blocksize) {
|
||||||
log_info("%s[%u:%u] %.*s", msg, (unsigned)length,
|
log_info("%s[%u:%u] %.*s", msg, (unsigned)length,
|
||||||
(unsigned)i, blocksize, buf+i);
|
(unsigned)i/2, blocksize, buf+i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(buf);
|
free(buf);
|
||||||
|
|
|
||||||
|
|
@ -218,7 +218,7 @@ key_entry_setup(struct region* region,
|
||||||
*d = region_alloc(region, sizeof(**d));
|
*d = region_alloc(region, sizeof(**d));
|
||||||
if(!*d)
|
if(!*d)
|
||||||
return 0;
|
return 0;
|
||||||
(*k)->entry.data = d;
|
(*k)->entry.data = *d;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -248,8 +248,8 @@ key_entry_create_rrset(struct region* region,
|
||||||
rrset->entry.data;
|
rrset->entry.data;
|
||||||
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 = rd->ttl;
|
log_info("New key entry TTL is now+%d", (int)rd->ttl);
|
||||||
log_info("New key entry TTL is %d", (int)d->ttl);
|
d->ttl = rd->ttl + time(NULL);
|
||||||
d->isbad = 0;
|
d->isbad = 0;
|
||||||
d->rrset_type = ntohs(rrset->rk.type);
|
d->rrset_type = ntohs(rrset->rk.type);
|
||||||
d->rrset_data = (struct packed_rrset_data*)region_alloc_init(region,
|
d->rrset_data = (struct packed_rrset_data*)region_alloc_init(region,
|
||||||
|
|
|
||||||
|
|
@ -200,7 +200,7 @@ ds_get_keytag(struct ub_packed_rrset_key* ds_rrset, size_t ds_idx)
|
||||||
if(len < 2+2)
|
if(len < 2+2)
|
||||||
return 0;
|
return 0;
|
||||||
memmove(&t, rdata+2, 2);
|
memmove(&t, rdata+2, 2);
|
||||||
return t;
|
return ntohs(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -430,6 +430,7 @@ dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
|
||||||
int algo = rrset_get_sig_algo(rrset, sig_idx);
|
int algo = rrset_get_sig_algo(rrset, sig_idx);
|
||||||
size_t i, num = rrset_get_count(dnskey);
|
size_t i, num = rrset_get_count(dnskey);
|
||||||
size_t numchecked = 0;
|
size_t numchecked = 0;
|
||||||
|
verbose(VERB_ALGO, "verify sig %d %d", (int)tag, algo);
|
||||||
|
|
||||||
for(i=0; i<num; i++) {
|
for(i=0; i<num; i++) {
|
||||||
/* see if key matches keytag and algo */
|
/* see if key matches keytag and algo */
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,9 @@ verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve,
|
||||||
!= ds_get_keytag(ds_rrset, ds_idx)) {
|
!= ds_get_keytag(ds_rrset, ds_idx)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
verbose(VERB_ALGO, "attempt DS match algo %d keytag %d",
|
||||||
|
ds_get_key_algo(ds_rrset, ds_idx),
|
||||||
|
ds_get_keytag(ds_rrset, ds_idx));
|
||||||
|
|
||||||
/* Convert the candidate DNSKEY into a hash using the
|
/* Convert the candidate DNSKEY into a hash using the
|
||||||
* same DS hash algorithm. */
|
* same DS hash algorithm. */
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,7 @@ needs_validation(struct module_qstate* qstate, struct val_qstate* vq)
|
||||||
|
|
||||||
/* If the CD bit is on in the original request, then we don't bother to
|
/* If the CD bit is on in the original request, then we don't bother to
|
||||||
* validate anything.*/
|
* validate anything.*/
|
||||||
if(qstate->query_flags | BIT_CD) {
|
if(qstate->query_flags & BIT_CD) {
|
||||||
verbose(VERB_ALGO, "not validating response due to CD bit");
|
verbose(VERB_ALGO, "not validating response due to CD bit");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -357,7 +357,8 @@ val_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||||
log_query_info(VERB_DETAIL, "validator operate: chased to",
|
log_query_info(VERB_DETAIL, "validator operate: chased to",
|
||||||
&vq->qchase);
|
&vq->qchase);
|
||||||
(void)outbound;
|
(void)outbound;
|
||||||
if(event == module_event_new || event == module_event_pass) {
|
if(event == module_event_new ||
|
||||||
|
(event == module_event_pass && vq == NULL)) {
|
||||||
/* pass request to next module, to get it */
|
/* pass request to next module, to get it */
|
||||||
verbose(VERB_ALGO, "validator: pass to next module");
|
verbose(VERB_ALGO, "validator: pass to next module");
|
||||||
qstate->ext_state[id] = module_wait_module;
|
qstate->ext_state[id] = module_wait_module;
|
||||||
|
|
@ -392,6 +393,12 @@ val_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||||
val_handle(qstate, vq, ve, id);
|
val_handle(qstate, vq, ve, id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(event == module_event_pass) {
|
||||||
|
qstate->ext_state[id] = module_error; /* override this */
|
||||||
|
/* continue processing, since val_env exists */
|
||||||
|
val_handle(qstate, vq, ve, id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
log_err("validator: bad event %s", strmodulevent(event));
|
log_err("validator: bad event %s", strmodulevent(event));
|
||||||
qstate->ext_state[id] = module_error;
|
qstate->ext_state[id] = module_error;
|
||||||
return;
|
return;
|
||||||
|
|
@ -448,6 +455,7 @@ primeResponseToKE(int rcode, struct dns_msg* msg, struct trust_anchor* ta,
|
||||||
sec = sec_status_secure;
|
sec = sec_status_secure;
|
||||||
else
|
else
|
||||||
sec = sec_status_bogus;
|
sec = sec_status_bogus;
|
||||||
|
log_info("priming DS result %s", sec_status_to_string(sec));
|
||||||
}
|
}
|
||||||
if(sec != sec_status_secure && ta->dnskey_rrset) {
|
if(sec != sec_status_secure && ta->dnskey_rrset) {
|
||||||
sec = val_verify_rrset(qstate->env, ve, dnskey_rrset,
|
sec = val_verify_rrset(qstate->env, ve, dnskey_rrset,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue