From 05739b0e5d243339bae473d68b18070ab0882249 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Thu, 12 Apr 2018 16:21:43 +0200 Subject: [PATCH] Fix the dns_random unit tests, test all available backends --- pdns/dns_random.cc | 42 +++++----- pdns/dns_random.hh | 2 +- pdns/recursordist/Makefile.am | 2 +- pdns/test-dns_random_hh.cc | 149 +++++++++++++++++++++++++++++++++- 4 files changed, 170 insertions(+), 25 deletions(-) diff --git a/pdns/dns_random.cc b/pdns/dns_random.cc index a5503bb9a..4357af562 100644 --- a/pdns/dns_random.cc +++ b/pdns/dns_random.cc @@ -81,12 +81,12 @@ kiss_rand(void) } #endif -static void dns_random_setup(void) +static void dns_random_setup(bool force=false) { string rdev; string rng; /* check if selection has been done */ - if (chosen_rng > RNG_UNINITIALIZED) + if (chosen_rng > RNG_UNINITIALIZED && !force) return; /* XXX: A horrible hack to allow using dns_random in places where arguments are not available. @@ -134,13 +134,13 @@ static void dns_random_setup(void) g_log<(__LINE__)); // cannot be reached + throw std::runtime_error("Unreachable at " __FILE__ ":" + boost::lexical_cast(__LINE__)); // cannot be reached case RNG_SODIUM: #if defined(HAVE_RANDOMBYTES_STIR) && !defined(USE_URANDOM_ONLY) return static_cast(randombytes_uniform(static_cast(upper_bound))); #else - throw PDNSException("Unreachable at " __FILE__ ":" + boost::lexical_cast(__LINE__)); // cannot be reached + throw std::runtime_error("Unreachable at " __FILE__ ":" + boost::lexical_cast(__LINE__)); // cannot be reached #endif /* RND_SODIUM */ case RNG_OPENSSL: { #if defined(HAVE_RAND_BYTES) && !defined(USE_URANDOM_ONLY) unsigned int num=0; while(num < min) { if (RAND_bytes(reinterpret_cast(&num), sizeof(num)) < 1) - throw PDNSException("Openssl RNG was not seeded"); + throw std::runtime_error("Openssl RNG was not seeded"); } return num % upper_bound; #else - throw PDNSException("Unreachable at " __FILE__ ":" + boost::lexical_cast(__LINE__)); // cannot be reached + throw std::runtime_error("Unreachable at " __FILE__ ":" + boost::lexical_cast(__LINE__)); // cannot be reached #endif /* RNG_OPENSSL */ } case RNG_GETRANDOM: { @@ -262,25 +262,25 @@ unsigned int dns_random(unsigned int upper_bound) { unsigned int num=0; while(num < min) { if (getrandom(&num, sizeof(num), 0) != sizeof(num)) - throw PDNSException("getrandom() failed: " + std::string(strerror(errno))); + throw std::runtime_error("getrandom() failed: " + std::string(strerror(errno))); } return num % upper_bound; #else - throw PDNSException("Unreachable at " __FILE__ ":" + boost::lexical_cast(__LINE__)); // cannot be reached + throw std::runtime_error("Unreachable at " __FILE__ ":" + boost::lexical_cast(__LINE__)); // cannot be reached #endif } case RNG_ARC4RANDOM: #if defined(HAVE_ARC4RANDOM) && !defined(USE_URANDOM_ONLY) return static_cast(arc4random_uniform(static_cast(upper_bound))); #else - throw PDNSException("Unreachable at " __FILE__ ":" + boost::lexical_cast(__LINE__)); // cannot be reached + throw std::runtime_error("Unreachable at " __FILE__ ":" + boost::lexical_cast(__LINE__)); // cannot be reached #endif case RNG_URANDOM: { unsigned int num = 0; while(num < min) { if (read(urandom_fd, &num, sizeof(num)) < 0) { (void)close(urandom_fd); - throw PDNSException("Cannot read random device"); + throw std::runtime_error("Cannot read random device"); } } return num % upper_bound; @@ -294,6 +294,6 @@ unsigned int dns_random(unsigned int upper_bound) { } #endif default: - throw PDNSException("Unreachable at " __FILE__ ":" + boost::lexical_cast(__LINE__)); // cannot be reached + throw std::runtime_error("Unreachable at " __FILE__ ":" + boost::lexical_cast(__LINE__)); // cannot be reached }; } diff --git a/pdns/dns_random.hh b/pdns/dns_random.hh index d4a869a09..c729da4bd 100644 --- a/pdns/dns_random.hh +++ b/pdns/dns_random.hh @@ -22,7 +22,7 @@ #ifndef PDNS_DNS_RANDOM #define PDNS_DNS_RANDOM -void dns_random_init(const std::string& data = ""); +void dns_random_init(const std::string& data = "", bool force_reinit = false); unsigned int dns_random(unsigned int n); #endif diff --git a/pdns/recursordist/Makefile.am b/pdns/recursordist/Makefile.am index a8580377c..f5e6afdd1 100644 --- a/pdns/recursordist/Makefile.am +++ b/pdns/recursordist/Makefile.am @@ -190,7 +190,7 @@ testrunner_SOURCES = \ base32.cc \ base64.cc base64.hh \ dns.cc dns.hh \ - dns_random_urandom.cc dns_random.hh \ + dns_random.cc dns_random.hh \ dnslabeltext.cc \ dnsname.cc dnsname.hh \ dnsparser.hh dnsparser.cc \ diff --git a/pdns/test-dns_random_hh.cc b/pdns/test-dns_random_hh.cc index aadb8864f..9b16276ec 100644 --- a/pdns/test-dns_random_hh.cc +++ b/pdns/test-dns_random_hh.cc @@ -15,6 +15,7 @@ #include #include +#include "arguments.hh" #include "dns_random.hh" #include "namespaces.hh" @@ -33,9 +34,12 @@ typedef accumulator_set< BOOST_AUTO_TEST_SUITE(test_dns_random_hh) +BOOST_AUTO_TEST_CASE(test_dns_random_auto_average, * boost::unit_test::depends_on("test_dns_random_hh/test_dns_random_uninit")) { + ::arg().set("rng")="auto"; + ::arg().set("entropy-source")="/dev/urandom"; -BOOST_AUTO_TEST_CASE(test_dns_random_average) { + dns_random_init("", true); acc_t acc; @@ -44,11 +48,152 @@ BOOST_AUTO_TEST_CASE(test_dns_random_average) { } BOOST_CHECK_CLOSE(0.5, median(acc), 2.0); // within 2% BOOST_CHECK_CLOSE(0.5, mean(acc), 2.0); - // please add covariance tests, chi-square, Kolmogorov-Smirnov } +BOOST_AUTO_TEST_CASE(test_dns_random_urandom_average, * boost::unit_test::depends_on("test_dns_random_hh/test_dns_random_uninit")) { + + ::arg().set("rng")="urandom"; + ::arg().set("entropy-source")="/dev/urandom"; + + dns_random_init("", true); + + acc_t acc; + + for(unsigned int n=0; n < 100000; ++n) { + acc(dns_random(100000)/100000.0); + } + BOOST_CHECK_CLOSE(0.5, median(acc), 2.0); // within 2% + BOOST_CHECK_CLOSE(0.5, mean(acc), 2.0); + + // please add covariance tests, chi-square, Kolmogorov-Smirnov +} + +BOOST_AUTO_TEST_CASE(test_dns_random_garbage, * boost::unit_test::depends_on("test_dns_random_hh/test_dns_random_uninit")) { + + ::arg().set("rng")="garbage"; + ::arg().set("entropy-source")="/dev/urandom"; + + BOOST_CHECK_THROW(dns_random_init("", true), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(test_dns_random_uninit) { + + /* should still work without the explicit call to dns_random_init() */ + ::arg().set("rng")="auto"; + ::arg().set("entropy-source")="/dev/urandom"; + + acc_t acc; + + for(unsigned int n=0; n < 100000; ++n) { + acc(dns_random(100000)/100000.0); + } + BOOST_CHECK_CLOSE(0.5, median(acc), 2.0); // within 2% + BOOST_CHECK_CLOSE(0.5, mean(acc), 2.0); + + // please add covariance tests, chi-square, Kolmogorov-Smirnov +} + +#if defined(HAVE_GETRANDOM) +BOOST_AUTO_TEST_CASE(test_dns_random_getrandom_average, * boost::unit_test::depends_on("test_dns_random_hh/test_dns_random_uninit")) { + + ::arg().set("rng")="getrandom"; + ::arg().set("entropy-source")="/dev/urandom"; + + dns_random_init("", true); + + acc_t acc; + + for(unsigned int n=0; n < 100000; ++n) { + acc(dns_random(100000)/100000.0); + } + BOOST_CHECK_CLOSE(0.5, median(acc), 2.0); // within 2% + BOOST_CHECK_CLOSE(0.5, mean(acc), 2.0); + + // please add covariance tests, chi-square, Kolmogorov-Smirnov +} +#endif + +#if defined(HAVE_ARC4RANDOM) +BOOST_AUTO_TEST_CASE(test_dns_random_getrandom_average, * boost::unit_test::depends_on("test_dns_random_hh/test_dns_random_uninit")) { + + ::arg().set("rng")="arc4random"; + ::arg().set("entropy-source")="/dev/urandom"; + + dns_random_init("", true); + + acc_t acc; + + for(unsigned int n=0; n < 100000; ++n) { + acc(dns_random(100000)/100000.0); + } + BOOST_CHECK_CLOSE(0.5, median(acc), 2.0); // within 2% + BOOST_CHECK_CLOSE(0.5, mean(acc), 2.0); + + // please add covariance tests, chi-square, Kolmogorov-Smirnov +} +#endif + +#if defined(HAVE_RANDOMBYTES_STIR) +BOOST_AUTO_TEST_CASE(test_dns_random_sodium_average, * boost::unit_test::depends_on("test_dns_random_hh/test_dns_random_uninit")) { + + ::arg().set("rng")="sodium"; + ::arg().set("entropy-source")="/dev/urandom"; + + dns_random_init("", true); + + acc_t acc; + + for(unsigned int n=0; n < 100000; ++n) { + acc(dns_random(100000)/100000.0); + } + BOOST_CHECK_CLOSE(0.5, median(acc), 2.0); // within 2% + BOOST_CHECK_CLOSE(0.5, mean(acc), 2.0); + + // please add covariance tests, chi-square, Kolmogorov-Smirnov +} +#endif + +#if defined(HAVE_RAND_BYTES) +BOOST_AUTO_TEST_CASE(test_dns_random_openssl_average, * boost::unit_test::depends_on("test_dns_random_hh/test_dns_random_uninit")) { + + ::arg().set("rng")="openssl"; + ::arg().set("entropy-source")="/dev/urandom"; + + dns_random_init("", true); + + acc_t acc; + + for(unsigned int n=0; n < 100000; ++n) { + acc(dns_random(100000)/100000.0); + } + BOOST_CHECK_CLOSE(0.5, median(acc), 2.0); // within 2% + BOOST_CHECK_CLOSE(0.5, mean(acc), 2.0); + + // please add covariance tests, chi-square, Kolmogorov-Smirnov +} +#endif + +#if defined(HAVE_KISS_RNG) +BOOST_AUTO_TEST_CASE(test_dns_random_kiss_average, * boost::unit_test::depends_on("test_dns_random_hh/test_dns_random_uninit")) { + + ::arg().set("rng")="kiss"; + ::arg().set("entropy-source")="/dev/urandom"; + + dns_random_init("", true); + + acc_t acc; + + for(unsigned int n=0; n < 100000; ++n) { + acc(dns_random(100000)/100000.0); + } + BOOST_CHECK_CLOSE(0.5, median(acc), 2.0); // within 2% + BOOST_CHECK_CLOSE(0.5, mean(acc), 2.0); + + // please add covariance tests, chi-square, Kolmogorov-Smirnov +} +#endif BOOST_AUTO_TEST_SUITE_END() -- 2.40.0