]> granicus.if.org Git - pdns/commitdiff
Fix the dns_random unit tests, test all available backends
authorRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 12 Apr 2018 14:21:43 +0000 (16:21 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 12 Apr 2018 14:21:43 +0000 (16:21 +0200)
pdns/dns_random.cc
pdns/dns_random.hh
pdns/recursordist/Makefile.am
pdns/test-dns_random_hh.cc

index a5503bb9af3e319142cb29e298912845dc425272..4357af56258f803b7478fa8cba1163d14965014c 100644 (file)
@@ -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<<Logger::Warning<<"kiss rng should not be used in production environment"<<std::endl;
 #endif
   } else {
-    throw PDNSException("Unsupported rng '" + rng + "'");
+    throw std::runtime_error("Unsupported rng '" + rng + "'");
   }
 
 # if defined(HAVE_RANDOMBYTES_STIR)
   if (chosen_rng == RNG_SODIUM) {
     if (sodium_init() == -1)
-      throw PDNSException("Unable to initialize sodium crypto library");
+      throw std::runtime_error("Unable to initialize sodium crypto library");
     /*  make sure it's set up */
     randombytes_stir();
   }
@@ -163,26 +163,26 @@ static void dns_random_setup(void)
     int ret;
     unsigned char buf[1];
     if ((ret = RAND_bytes(buf, sizeof(buf))) == -1)
-      throw PDNSException("RAND_bytes not supported by current SSL engine");
+      throw std::runtime_error("RAND_bytes not supported by current SSL engine");
     if (ret == 0)
-      throw PDNSException("Openssl RNG was not seeded");
+      throw std::runtime_error("Openssl RNG was not seeded");
   }
 # endif
 #endif /* USE_URANDOM_ONLY */
   if (chosen_rng == RNG_URANDOM) {
     urandom_fd = open(rdev.c_str(), O_RDONLY);
     if (urandom_fd == -1)
-      throw PDNSException("Cannot open " + rdev + ": " + std::string(strerror(errno)));
+      throw std::runtime_error("Cannot open " + rdev + ": " + std::string(strerror(errno)));
   }
 #if defined(HAVE_KISS_RNG)
   if (chosen_rng == RNG_KISS) {
     unsigned int seed;
     urandom_fd = open(rdev.c_str(), O_RDONLY);
     if (urandom_fd == -1)
-      throw PDNSException("Cannot open " + rdev + ": " + std::string(strerror(errno)));
+      throw std::runtime_error("Cannot open " + rdev + ": " + std::string(strerror(errno)));
     if (read(urandom_fd, &seed, sizeof(seed)) < 0) {
       (void)close(urandom_fd);
-      throw PDNSException("Cannot read random device");
+      throw std::runtime_error("Cannot read random device");
     }
     kiss_init(seed);
     (void)close(urandom_fd);
@@ -190,8 +190,8 @@ static void dns_random_setup(void)
 #endif
 }
 
-void dns_random_init(const string& data __attribute__((unused))) {
-  dns_random_setup();
+void dns_random_init(const string& data __attribute__((unused)), bool force) {
+  dns_random_setup(force);
   (void)dns_random(1);
   // init should occur already in dns_random_setup
   // this interface is only for KISS
@@ -200,7 +200,7 @@ void dns_random_init(const string& data __attribute__((unused))) {
   if (chosen_rng != RNG_KISS)
     return;
   if (data.size() != 16)
-    throw PDNSException("invalid seed");
+    throw std::runtime_error("invalid seed");
   seed = (data[0] + (data[1]<<8) + (data[2]<<16) + (data[3]<<24)) ^
          (data[4] + (data[5]<<8) + (data[6]<<16) + (data[7]<<24)) ^
          (data[8] + (data[9]<<8) + (data[10]<<16) + (data[11]<<24)) ^
@@ -238,23 +238,23 @@ unsigned int dns_random(unsigned int upper_bound) {
 
   switch(chosen_rng) {
   case RNG_UNINITIALIZED:
-    throw PDNSException("Unreachable at " __FILE__ ":" + boost::lexical_cast<std::string>(__LINE__)); // cannot be reached
+    throw std::runtime_error("Unreachable at " __FILE__ ":" + boost::lexical_cast<std::string>(__LINE__)); // cannot be reached
   case RNG_SODIUM:
 #if defined(HAVE_RANDOMBYTES_STIR) && !defined(USE_URANDOM_ONLY)
     return static_cast<unsigned int>(randombytes_uniform(static_cast<uint32_t>(upper_bound)));
 #else
-    throw PDNSException("Unreachable at " __FILE__ ":" + boost::lexical_cast<std::string>(__LINE__)); // cannot be reached
+    throw std::runtime_error("Unreachable at " __FILE__ ":" + boost::lexical_cast<std::string>(__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<unsigned char*>(&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<std::string>(__LINE__)); // cannot be reached
+      throw std::runtime_error("Unreachable at " __FILE__ ":" + boost::lexical_cast<std::string>(__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<std::string>(__LINE__)); // cannot be reached
+      throw std::runtime_error("Unreachable at " __FILE__ ":" + boost::lexical_cast<std::string>(__LINE__)); // cannot be reached
 #endif
       }
   case RNG_ARC4RANDOM:
 #if defined(HAVE_ARC4RANDOM) && !defined(USE_URANDOM_ONLY)
     return static_cast<unsigned int>(arc4random_uniform(static_cast<uint32_t>(upper_bound)));
 #else
-    throw PDNSException("Unreachable at " __FILE__ ":" + boost::lexical_cast<std::string>(__LINE__)); // cannot be reached
+    throw std::runtime_error("Unreachable at " __FILE__ ":" + boost::lexical_cast<std::string>(__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<std::string>(__LINE__)); // cannot be reached
+    throw std::runtime_error("Unreachable at " __FILE__ ":" + boost::lexical_cast<std::string>(__LINE__)); // cannot be reached
   };
 }
index d4a869a09bd83a29a2b905bc2e3596e3c5f162ab..c729da4bd00fb3b5018e60a889c9ce237ed0b098 100644 (file)
@@ -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
index a8580377c1e74ea667be8712acaa0dc4ac110da4..f5e6afdd188d97732c0bab6634e4b076ce0e56fc 100644 (file)
@@ -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 \
index aadb8864f0ac5f049ccf95ec93c7dcfac59249e7..9b16276ec7e4b989b0283db3b3992dbdbb9be49a 100644 (file)
@@ -15,6 +15,7 @@
 #include <boost/accumulators/accumulators.hpp>
 #include <boost/accumulators/statistics.hpp>
 
+#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()