Sync with unbound

This commit is contained in:
Willem Toorop 2017-03-20 16:41:57 +01:00
parent ed66edf52a
commit a3fe958387
6 changed files with 207 additions and 138 deletions

View File

@ -311,6 +311,15 @@ AC_INCLUDES_DEFAULT
fi
AC_ARG_ENABLE(sha1, AC_HELP_STRING([--disable-sha1], [Disable SHA1 RRSIG support, does not disable nsec3 support]))
case "$enable_sha1" in
no)
;;
yes|*)
AC_DEFINE([USE_SHA1], [1], [Define this to enable SHA1 support.])
;;
esac
AC_ARG_ENABLE(sha2, AC_HELP_STRING([--disable-sha2], [Disable SHA256 and SHA512 RRSIG support]))
case "$enable_sha2" in
no)

View File

@ -45,7 +45,6 @@ on 1 byte), but shoehorning those bytes into integers efficiently is messy.
/*#define SELF_TEST 1*/
#include "config.h"
#include "util/lookup3.h"
#include "util/storage/lookup3.h"
#include <stdio.h> /* defines printf for tests */
#include <time.h> /* defines time_t for timings in the test */

View File

@ -41,7 +41,6 @@
*/
#include "config.h"
#include "util/lruhash.h"
#include "util/storage/lruhash.h"
#include "util/fptr_wlist.h"
@ -297,92 +296,6 @@ lru_touch(struct lruhash* table, struct lruhash_entry* entry)
lru_front(table, entry);
}
/*
* Demote: the opposite of touch, move an entry to the bottom
* of the LRU pile.
*/
void
lru_demote(struct lruhash* table, struct lruhash_entry* entry)
{
log_assert(table && entry);
if (entry == table->lru_end)
return; /* nothing to do */
/* remove from current lru position */
lru_remove(table, entry);
/* add at end */
entry->lru_next = NULL;
entry->lru_prev = table->lru_end;
if (table->lru_end == NULL)
{
table->lru_start = entry;
}
else
{
table->lru_end->lru_next = entry;
}
table->lru_end = entry;
}
struct lruhash_entry*
lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* cb_arg)
{
struct lruhash_bin* bin;
struct lruhash_entry* found, *reclaimlist = NULL;
size_t need_size;
fptr_ok(fptr_whitelist_hash_sizefunc(table->sizefunc));
fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc));
fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc));
fptr_ok(fptr_whitelist_hash_compfunc(table->compfunc));
fptr_ok(fptr_whitelist_hash_markdelfunc(table->markdelfunc));
need_size = table->sizefunc(entry->key, data);
if (cb_arg == NULL) cb_arg = table->cb_arg;
/* find bin */
lock_quick_lock(&table->lock);
bin = &table->array[hash & table->size_mask];
lock_quick_lock(&bin->lock);
/* see if entry exists already */
if ((found = bin_find_entry(table, bin, hash, entry->key)) != NULL) {
/* if so: keep the existing data - acquire a writelock */
lock_rw_wrlock(&found->lock);
}
else
{
/* if not: add to bin */
entry->overflow_next = bin->overflow_list;
bin->overflow_list = entry;
lru_front(table, entry);
table->num++;
table->space_used += need_size;
/* return the entry that was presented, and lock it */
found = entry;
lock_rw_wrlock(&found->lock);
}
lock_quick_unlock(&bin->lock);
if (table->space_used > table->space_max)
reclaim_space(table, &reclaimlist);
if (table->num >= table->size)
table_grow(table);
lock_quick_unlock(&table->lock);
/* finish reclaim if any (outside of critical region) */
while (reclaimlist) {
struct lruhash_entry* n = reclaimlist->overflow_next;
void* d = reclaimlist->data;
(*table->delkeyfunc)(reclaimlist->key, cb_arg);
(*table->deldatafunc)(d, cb_arg);
reclaimlist = n;
}
/* return the entry that was selected */
return found;
}
void
lruhash_insert(struct lruhash* table, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* cb_arg)
@ -630,3 +543,89 @@ lruhash_traverse(struct lruhash* h, int wr,
}
lock_quick_unlock(&h->lock);
}
/*
* Demote: the opposite of touch, move an entry to the bottom
* of the LRU pile.
*/
void
lru_demote(struct lruhash* table, struct lruhash_entry* entry)
{
log_assert(table && entry);
if (entry == table->lru_end)
return; /* nothing to do */
/* remove from current lru position */
lru_remove(table, entry);
/* add at end */
entry->lru_next = NULL;
entry->lru_prev = table->lru_end;
if (table->lru_end == NULL)
{
table->lru_start = entry;
}
else
{
table->lru_end->lru_next = entry;
}
table->lru_end = entry;
}
struct lruhash_entry*
lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* cb_arg)
{
struct lruhash_bin* bin;
struct lruhash_entry* found, *reclaimlist = NULL;
size_t need_size;
fptr_ok(fptr_whitelist_hash_sizefunc(table->sizefunc));
fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc));
fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc));
fptr_ok(fptr_whitelist_hash_compfunc(table->compfunc));
fptr_ok(fptr_whitelist_hash_markdelfunc(table->markdelfunc));
need_size = table->sizefunc(entry->key, data);
if (cb_arg == NULL) cb_arg = table->cb_arg;
/* find bin */
lock_quick_lock(&table->lock);
bin = &table->array[hash & table->size_mask];
lock_quick_lock(&bin->lock);
/* see if entry exists already */
if ((found = bin_find_entry(table, bin, hash, entry->key)) != NULL) {
/* if so: keep the existing data - acquire a writelock */
lock_rw_wrlock(&found->lock);
}
else
{
/* if not: add to bin */
entry->overflow_next = bin->overflow_list;
bin->overflow_list = entry;
lru_front(table, entry);
table->num++;
table->space_used += need_size;
/* return the entry that was presented, and lock it */
found = entry;
lock_rw_wrlock(&found->lock);
}
lock_quick_unlock(&bin->lock);
if (table->space_used > table->space_max)
reclaim_space(table, &reclaimlist);
if (table->num >= table->size)
table_grow(table);
lock_quick_unlock(&table->lock);
/* finish reclaim if any (outside of critical region) */
while (reclaimlist) {
struct lruhash_entry* n = reclaimlist->overflow_next;
void* d = reclaimlist->data;
(*table->delkeyfunc)(reclaimlist->key, cb_arg);
(*table->deldatafunc)(d, cb_arg);
reclaimlist = n;
}
/* return the entry that was selected */
return found;
}

View File

@ -46,12 +46,13 @@
#define lruhash_delete _getdns_lruhash_delete
#define lruhash_clear _getdns_lruhash_clear
#define lruhash_insert _getdns_lruhash_insert
#define lruhash_insert_or_retrieve _getdns_lruhash_insert_or_retrieve
#define lruhash_lookup _getdns_lruhash_lookup
#define lru_touch _getdns_lru_touch
#define lru_demote _getdns_lru_demote
#define lruhash_setmarkdel _getdns_lruhash_setmarkdel
#define lru_demote _getdns_lru_demote
#define lruhash_insert_or_retrieve _getdns_lruhash_insert_or_retrieve
#define lruhash_remove _getdns_lruhash_remove
#define bin_init _getdns_bin_init
#define bin_delete _getdns_bin_delete
@ -67,37 +68,4 @@
#define lruhash_traverse _getdns_lruhash_traverse
#include "util/orig-headers/lruhash.h"
/*
* Additional function definitions, not found in original header.
*/
/**
* Demote entry, so it becomes the least recently used in the LRU list.
* Caller must hold hash table lock. The entry must be inserted already.
* @param table: hash table.
* @param entry: entry to make last in LRU.
*/
void lru_demote(struct lruhash* table, struct lruhash_entry* entry);
/**
* Insert a new element into the hashtable, or retrieve the corresponding
* element of it exits.
*
* If key is already present data pointer in that entry is kept.
* If it is not present, a new entry is created. In that case,
* the space calculation function is called with the key, data.
* If necessary the least recently used entries are deleted to make space.
* If necessary the hash array is grown up.
*
* @param table: hash table.
* @param hash: hash value. User calculates the hash.
* @param entry: identifies the entry.
* @param data: the data.
* @param cb_override: if not null overrides the cb_arg for the deletefunc.
* @return: pointer to the existing entry if the key was already present,
* or to the entry argument if it was not.
*/
struct lruhash_entry* lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* cb_arg);
#endif

View File

@ -301,6 +301,38 @@ void lru_touch(struct lruhash* table, struct lruhash_entry* entry);
*/
void lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_type md);
/************************* getdns functions ************************/
/*** these are used by getdns only and not by unbound. ***/
/**
* Demote entry, so it becomes the least recently used in the LRU list.
* Caller must hold hash table lock. The entry must be inserted already.
* @param table: hash table.
* @param entry: entry to make last in LRU.
*/
void lru_demote(struct lruhash* table, struct lruhash_entry* entry);
/**
* Insert a new element into the hashtable, or retrieve the corresponding
* element of it exits.
*
* If key is already present data pointer in that entry is kept.
* If it is not present, a new entry is created. In that case,
* the space calculation function is called with the key, data.
* If necessary the least recently used entries are deleted to make space.
* If necessary the hash array is grown up.
*
* @param table: hash table.
* @param hash: hash value. User calculates the hash.
* @param entry: identifies the entry.
* @param data: the data.
* @param cb_override: if not null overrides the cb_arg for the deletefunc.
* @return: pointer to the existing entry if the key was already present,
* or to the entry argument if it was not.
*/
struct lruhash_entry* lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* cb_arg);
/************************* Internal functions ************************/
/*** these are only exposed for unit tests. ***/

View File

@ -74,6 +74,8 @@
/** fake DSA support for unit tests */
int fake_dsa = 0;
/** fake SHA1 support for unit tests */
int fake_sha1 = 0;
/* return size of digest if supported, or 0 otherwise */
size_t
@ -116,9 +118,12 @@ size_t
ds_digest_size_supported(int algo)
{
switch(algo) {
#ifdef HAVE_EVP_SHA1
case LDNS_SHA1:
#if defined(HAVE_EVP_SHA1) && defined(USE_SHA1)
return SHA_DIGEST_LENGTH;
#else
if(fake_sha1) return 20;
return 0;
#endif
#ifdef HAVE_EVP_SHA256
case LDNS_SHA256:
@ -158,7 +163,7 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
unsigned char* res)
{
switch(algo) {
#ifdef HAVE_EVP_SHA1
#if defined(HAVE_EVP_SHA1) && defined(USE_SHA1)
case LDNS_SHA1:
(void)SHA1(buf, len, res);
return 1;
@ -197,14 +202,22 @@ dnskey_algo_id_is_supported(int id)
return 0;
case LDNS_DSA:
case LDNS_DSA_NSEC3:
#ifdef USE_DSA
#if defined(USE_DSA) && defined(USE_SHA1)
return 1;
#else
if(fake_dsa) return 1;
if(fake_dsa || fake_sha1) return 1;
return 0;
#endif
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
#ifdef USE_SHA1
return 1;
#else
if(fake_sha1) return 1;
return 0;
#endif
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
case LDNS_RSASHA256:
#endif
@ -215,7 +228,10 @@ dnskey_algo_id_is_supported(int id)
case LDNS_ECDSAP256SHA256:
case LDNS_ECDSAP384SHA384:
#endif
#if (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) || defined(USE_ECDSA)
return 1;
#endif
#ifdef USE_GOST
case LDNS_ECC_GOST:
/* we support GOST if it can be loaded */
@ -392,13 +408,13 @@ static int
setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
unsigned char* key, size_t keylen)
{
#ifdef USE_DSA
#if defined(USE_DSA) && defined(USE_SHA1)
DSA* dsa;
#endif
RSA* rsa;
switch(algo) {
#ifdef USE_DSA
#if defined(USE_DSA) && defined(USE_SHA1)
case LDNS_DSA:
case LDNS_DSA_NSEC3:
*evp_key = EVP_PKEY_new();
@ -424,9 +440,13 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
#endif
break;
#endif /* USE_DSA */
#endif /* USE_DSA && USE_SHA1 */
#if defined(USE_SHA1) || (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2))
#ifdef USE_SHA1
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
#endif
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
case LDNS_RSASHA256:
#endif
@ -461,9 +481,14 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
*digest_type = EVP_sha512();
else
#endif
#ifdef USE_SHA1
*digest_type = EVP_sha1();
#else
{ verbose(VERB_QUERY, "no digest available"); return 0; }
#endif
break;
#endif /* defined(USE_SHA1) || (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) */
case LDNS_RSAMD5:
*evp_key = EVP_PKEY_new();
if(!*evp_key) {
@ -562,7 +587,11 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
EVP_PKEY *evp_key = NULL;
#ifndef USE_DSA
if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) && fake_dsa)
if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&(fake_dsa||fake_sha1))
return sec_status_secure;
#endif
#ifndef USE_SHA1
if(fake_sha1 && (algo == LDNS_DSA || algo == LDNS_DSA_NSEC3 || algo == LDNS_RSASHA1 || algo == LDNS_RSASHA1_NSEC3))
return sec_status_secure;
#endif
@ -706,8 +735,10 @@ ds_digest_size_supported(int algo)
{
/* uses libNSS */
switch(algo) {
#ifdef USE_SHA1
case LDNS_SHA1:
return SHA1_LENGTH;
#endif
#ifdef USE_SHA2
case LDNS_SHA256:
return SHA256_LENGTH;
@ -729,9 +760,11 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
{
/* uses libNSS */
switch(algo) {
#ifdef USE_SHA1
case LDNS_SHA1:
return HASH_HashBuf(HASH_AlgSHA1, res, buf, len)
== SECSuccess;
#endif
#if defined(USE_SHA2)
case LDNS_SHA256:
return HASH_HashBuf(HASH_AlgSHA256, res, buf, len)
@ -759,12 +792,15 @@ dnskey_algo_id_is_supported(int id)
case LDNS_RSAMD5:
/* RFC 6725 deprecates RSAMD5 */
return 0;
#ifdef USE_DSA
#if defined(USE_SHA1) || defined(USE_SHA2)
#if defined(USE_DSA) && defined(USE_SHA1)
case LDNS_DSA:
case LDNS_DSA_NSEC3:
#endif
#ifdef USE_SHA1
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
#endif
#ifdef USE_SHA2
case LDNS_RSASHA256:
#endif
@ -772,6 +808,8 @@ dnskey_algo_id_is_supported(int id)
case LDNS_RSASHA512:
#endif
return 1;
#endif /* SHA1 or SHA2 */
#ifdef USE_ECDSA
case LDNS_ECDSAP256SHA256:
case LDNS_ECDSAP384SHA384:
@ -1003,7 +1041,9 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
*/
switch(algo) {
#ifdef USE_DSA
#if defined(USE_SHA1) || defined(USE_SHA2)
#if defined(USE_DSA) && defined(USE_SHA1)
case LDNS_DSA:
case LDNS_DSA_NSEC3:
*pubkey = nss_buf2dsa(key, keylen);
@ -1015,8 +1055,10 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
/* no prefix for DSA verification */
break;
#endif
#ifdef USE_SHA1
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
#endif
#ifdef USE_SHA2
case LDNS_RSASHA256:
#endif
@ -1043,13 +1085,22 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
*prefixlen = sizeof(p_sha512);
} else
#endif
#ifdef USE_SHA1
{
*htype = HASH_AlgSHA1;
*prefix = p_sha1;
*prefixlen = sizeof(p_sha1);
}
#else
{
verbose(VERB_QUERY, "verify: no digest algo");
return 0;
}
#endif
break;
#endif /* SHA1 or SHA2 */
case LDNS_RSAMD5:
*pubkey = nss_buf2rsa(key, keylen);
if(!*pubkey) {
@ -1131,7 +1182,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
return sec_status_bogus;
}
#ifdef USE_DSA
#if defined(USE_DSA) && defined(USE_SHA1)
/* need to convert DSA, ECDSA signatures? */
if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3)) {
if(sigblock_len == 1+2*SHA1_LENGTH) {
@ -1312,7 +1363,12 @@ ds_digest_size_supported(int algo)
{
switch(algo) {
case LDNS_SHA1:
#ifdef USE_SHA1
return SHA1_DIGEST_SIZE;
#else
if(fake_sha1) return 20;
return 0;
#endif
#ifdef USE_SHA2
case LDNS_SHA256:
return SHA256_DIGEST_SIZE;
@ -1334,8 +1390,10 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
unsigned char* res)
{
switch(algo) {
#ifdef USE_SHA1
case LDNS_SHA1:
return _digest_nettle(SHA1_DIGEST_SIZE, buf, len, res);
#endif
#if defined(USE_SHA2)
case LDNS_SHA256:
return _digest_nettle(SHA256_DIGEST_SIZE, buf, len, res);
@ -1359,12 +1417,14 @@ dnskey_algo_id_is_supported(int id)
{
/* uses libnettle */
switch(id) {
#ifdef USE_DSA
#if defined(USE_DSA) && defined(USE_SHA1)
case LDNS_DSA:
case LDNS_DSA_NSEC3:
#endif
#ifdef USE_SHA1
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
#endif
#ifdef USE_SHA2
case LDNS_RSASHA256:
case LDNS_RSASHA512:
@ -1381,7 +1441,7 @@ dnskey_algo_id_is_supported(int id)
}
}
#ifdef USE_DSA
#if defined(USE_DSA) && defined(USE_SHA1)
static char *
_verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock,
unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
@ -1641,7 +1701,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
}
switch(algo) {
#ifdef USE_DSA
#if defined(USE_DSA) && defined(USE_SHA1)
case LDNS_DSA:
case LDNS_DSA_NSEC3:
*reason = _verify_nettle_dsa(buf, sigblock, sigblock_len, key, keylen);
@ -1651,9 +1711,11 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
return sec_status_secure;
#endif /* USE_DSA */
#ifdef USE_SHA1
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
digest_size = (digest_size ? digest_size : SHA1_DIGEST_SIZE);
#endif
#ifdef USE_SHA2
case LDNS_RSASHA256:
digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE);