neater errors for algo and key failure.

git-svn-id: file:///svn/unbound/trunk@1872 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2009-10-08 08:02:00 +00:00
parent 7782cf2b97
commit 2c33330994

View file

@ -459,6 +459,21 @@ dnskeyset_needs(struct ub_packed_rrset_key* dnskey, uint8_t needs[])
return total; return total;
} }
/** see which algo needed */
static int any_needed_bogus(uint8_t needs[])
{
int i;
/* first check if a needed algo was bogus - report that */
for(i=0; i<256; i++)
if(needs[i] == 2)
return 0;
/* now check which algo is missing */
for(i=0; i<256; i++)
if(needs[i] == 1)
return i;
return 0;
}
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,
@ -469,7 +484,7 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
rbtree_t* sortree = NULL; rbtree_t* sortree = NULL;
/* make sure that for all DNSKEY algorithms there are valid sigs */ /* make sure that for all DNSKEY algorithms there are valid sigs */
uint8_t needs[256]; /* 1 if need sig for that algorithm */ uint8_t needs[256]; /* 1 if need sig for that algorithm */
int sawbogus = 0; int alg;
num = rrset_get_sigcount(rrset); num = rrset_get_sigcount(rrset);
if(num == 0) { if(num == 0) {
@ -486,20 +501,31 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
/* see which algorithm has been fixed up */ /* see which algorithm has been fixed up */
if(sec == sec_status_secure) { if(sec == sec_status_secure) {
uint8_t a = (uint8_t)rrset_get_sig_algo(rrset, i); uint8_t a = (uint8_t)rrset_get_sig_algo(rrset, i);
if(needs[a] == 1) { if(needs[a]) {
needs[a] = 0; needs[a] = 0;
numneeds --; numneeds --;
if(numneeds == 0) /* done! */ if(numneeds == 0) /* done! */
return sec; return sec;
} }
} else if(sec == sec_status_bogus) {
uint8_t a = (uint8_t)rrset_get_sig_algo(rrset, i);
if(needs[a]) needs[a] = 2; /* need it, but bogus */
} }
else if(sec == sec_status_bogus)
sawbogus = 1;
} }
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)numneeds); "%d algorithms", (int)numneeds);
if(!sawbogus) if((alg=any_needed_bogus(needs)) != 0) {
char buf[256];
ldns_lookup_table *t = ldns_lookup_by_id(ldns_algorithms, alg);
if(t&&t->name)
snprintf(buf, sizeof(buf), "no signatures with "
"algorithm %s", t->name);
else snprintf(buf, sizeof(buf), "no signatures with "
"algorithm ALG%u", (unsigned)alg);
*reason = regional_strdup(env->scratch, buf);
if(!*reason)
*reason = "no signatures for all algorithms"; *reason = "no signatures for all algorithms";
}
return sec_status_bogus; return sec_status_bogus;
} }
@ -1372,12 +1398,14 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
* @param sigblock_len: length of sigblock data. * @param sigblock_len: length of sigblock data.
* @param key: public key data from DNSKEY RR. * @param key: public key data from DNSKEY RR.
* @param keylen: length of keydata. * @param keylen: length of keydata.
* @param reason: bogus reason in more detail.
* @return secure if verification succeeded, bogus on crypto failure, * @return secure if verification succeeded, bogus on crypto failure,
* unchecked on format errors and alloc failures. * unchecked on format errors and alloc failures.
*/ */
static enum sec_status static enum sec_status
verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock, verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock,
unsigned int sigblock_len, unsigned char* key, unsigned int keylen) unsigned int sigblock_len, unsigned char* key, unsigned int keylen,
char** reason)
{ {
const EVP_MD *digest_type; const EVP_MD *digest_type;
EVP_MD_CTX ctx; EVP_MD_CTX ctx;
@ -1386,6 +1414,7 @@ verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock,
if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) { if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) {
verbose(VERB_QUERY, "verify: failed to setup key"); verbose(VERB_QUERY, "verify: failed to setup key");
*reason = "use of key for crypto failed";
EVP_PKEY_free(evp_key); EVP_PKEY_free(evp_key);
return sec_status_bogus; return sec_status_bogus;
} }
@ -1394,6 +1423,7 @@ verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock,
sigblock_len == 1+2*SHA_DIGEST_LENGTH) { sigblock_len == 1+2*SHA_DIGEST_LENGTH) {
if(!setup_dsa_sig(&sigblock, &sigblock_len)) { if(!setup_dsa_sig(&sigblock, &sigblock_len)) {
verbose(VERB_QUERY, "verify: failed to setup DSA sig"); verbose(VERB_QUERY, "verify: failed to setup DSA sig");
*reason = "use of key for DSA crypto failed";
EVP_PKEY_free(evp_key); EVP_PKEY_free(evp_key);
return sec_status_bogus; return sec_status_bogus;
} }
@ -1432,6 +1462,7 @@ verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock,
return sec_status_secure; return sec_status_secure;
} else if(res == 0) { } else if(res == 0) {
verbose(VERB_QUERY, "verify: signature mismatch"); verbose(VERB_QUERY, "verify: signature mismatch");
*reason = "signature crypto failed";
return sec_status_bogus; return sec_status_bogus;
} }
@ -1564,13 +1595,12 @@ dnskey_verify_rrset_sig(struct regional* region, ldns_buffer* buf,
/* verify */ /* verify */
sec = verify_canonrrset(buf, (int)sig[2+2], sec = verify_canonrrset(buf, (int)sig[2+2],
sigblock, sigblock_len, key, keylen); sigblock, sigblock_len, key, keylen, reason);
/* check if TTL is too high - reduce if so */ /* check if TTL is too high - reduce if so */
if(sec == sec_status_secure) { if(sec == sec_status_secure) {
adjust_ttl(ve, now, rrset, sig+2+4, sig+2+8, sig+2+12); adjust_ttl(ve, now, rrset, sig+2+4, sig+2+8, sig+2+12);
} else if(sec == sec_status_bogus) }
*reason = "signature crypto failed";
return sec; return sec;
} }