diff --git a/configure.ac b/configure.ac index bb2fa22f..3cb6d24c 100644 --- a/configure.ac +++ b/configure.ac @@ -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) diff --git a/src/util/lookup3.c b/src/util/lookup3.c index dedcdcaf..e9b05af3 100644 --- a/src/util/lookup3.c +++ b/src/util/lookup3.c @@ -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 /* defines printf for tests */ #include /* defines time_t for timings in the test */ diff --git a/src/util/lruhash.c b/src/util/lruhash.c index fd091ef9..0003ff49 100644 --- a/src/util/lruhash.c +++ b/src/util/lruhash.c @@ -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; +} + diff --git a/src/util/lruhash.h b/src/util/lruhash.h index 8c0d1a18..6796a68d 100644 --- a/src/util/lruhash.h +++ b/src/util/lruhash.h @@ -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 diff --git a/src/util/orig-headers/lruhash.h b/src/util/orig-headers/lruhash.h index c3937408..af06b622 100644 --- a/src/util/orig-headers/lruhash.h +++ b/src/util/orig-headers/lruhash.h @@ -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. ***/ diff --git a/src/util/val_secalgo.c b/src/util/val_secalgo.c index 302820fc..be88ff43 100644 --- a/src/util/val_secalgo.c +++ b/src/util/val_secalgo.c @@ -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);