Parcourir la source

[trac812next] unified "fake time" hook in lib/util/time_utilities.
not directly related to the main purpose of this branch, but this is
a deferred cleanup from the initial step of this task.

JINMEI Tatuya il y a 14 ans
Parent
commit
29170e28d1

+ 5 - 6
src/lib/dns/tests/message_unittest.cc

@@ -17,6 +17,8 @@
 #include <exceptions/exceptions.h>
 
 #include <util/buffer.h>
+#include <util/time_utilities.h>
+
 #include <dns/edns.h>
 #include <dns/exceptions.h>
 #include <dns/message.h>
@@ -57,16 +59,13 @@ using namespace isc::dns::rdata;
 const uint16_t Message::DEFAULT_MAX_UDPSIZE;
 const Name test_name("test.example.com");
 
-// See dnssectime.cc
 namespace isc {
-namespace dns {
-namespace tsig {
+namespace util {
 namespace detail {
 extern int64_t (*gettimeFunction)();
 }
 }
 }
-}
 
 namespace {
 class MessageTest : public ::testing::Test {
@@ -569,7 +568,7 @@ TEST_F(MessageTest, toWireWithTSIG) {
     // TSIG are tested in the tsig tests.  We only check the message contains
     // a TSIG at the end and the ARCOUNT of the header is updated.
 
-    tsig::detail::gettimeFunction = testGetTime<0x4da8877a>;
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
 
     message_render.setQid(0x2d65);
 
@@ -583,7 +582,7 @@ TEST_F(MessageTest, toWireWithTSIG) {
 TEST_F(MessageTest, toWireWithEDNSAndTSIG) {
     // Similar to the previous test, but with an EDNS before TSIG.
     // The wire data check will confirm the ordering.
-    tsig::detail::gettimeFunction = testGetTime<0x4db60d1f>;
+    isc::util::detail::gettimeFunction = testGetTime<0x4db60d1f>;
 
     message_render.setQid(0x6cd);
 

+ 14 - 15
src/lib/dns/tests/tsig_unittest.cc

@@ -26,6 +26,7 @@
 #include <util/buffer.h>
 #include <util/encode/base64.h>
 #include <util/unittests/newhook.h>
+#include <util/time_utilities.h>
 
 #include <dns/message.h>
 #include <dns/messagerenderer.h>
@@ -50,14 +51,12 @@ using isc::UnitTestUtil;
 
 // See dnssectime.cc
 namespace isc {
-namespace dns {
-namespace tsig {
+namespace util {
 namespace detail {
 extern int64_t (*gettimeFunction)();
 }
 }
 }
-}
 
 namespace {
 // See dnssectime_unittest.cc
@@ -76,7 +75,7 @@ protected:
     {
         // Make sure we use the system time by default so that we won't be
         // confused due to other tests that tweak the time.
-        tsig::detail::gettimeFunction = NULL;
+        isc::util::detail::gettimeFunction = NULL;
 
         decodeBase64("SFuWd/q99SzF8Yzd1QbB9g==", secret);
         tsig_ctx.reset(new TSIGContext(TSIGKey(test_name,
@@ -88,7 +87,7 @@ protected:
                                                       secret.size())));
     }
     ~TSIGTest() {
-        tsig::detail::gettimeFunction = NULL;
+        isc::util::detail::gettimeFunction = NULL;
     }
 
     // Many of the tests below create some DNS message and sign it under
@@ -210,7 +209,7 @@ const uint8_t common_expected_mac[] = {
     0x21, 0xce, 0x6c, 0x6f, 0xff, 0x1e, 0x9e, 0xf3
 };
 TEST_F(TSIGTest, sign) {
-    tsig::detail::gettimeFunction = testGetTime<0x4da8877a>;
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
 
     {
         SCOPED_TRACE("Sign test for query");
@@ -224,7 +223,7 @@ TEST_F(TSIGTest, sign) {
 // non canonical) characters.  The digest must be the same.  It should actually
 // be ensured at the level of TSIGKey, but we confirm that at this level, too.
 TEST_F(TSIGTest, signUsingUpperCasedKeyName) {
-    tsig::detail::gettimeFunction = testGetTime<0x4da8877a>;
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
 
     TSIGContext cap_ctx(TSIGKey(Name("WWW.EXAMPLE.COM"),
                                 TSIGKey::HMACMD5_NAME(),
@@ -240,7 +239,7 @@ TEST_F(TSIGTest, signUsingUpperCasedKeyName) {
 
 // Same as the previous test, but for the algorithm name.
 TEST_F(TSIGTest, signUsingUpperCasedAlgorithmName) {
-    tsig::detail::gettimeFunction = testGetTime<0x4da8877a>;
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
 
     TSIGContext cap_ctx(TSIGKey(test_name,
                                 Name("HMAC-md5.SIG-alg.REG.int"),
@@ -326,7 +325,7 @@ TEST_F(TSIGTest, signExceptionSafety) {
 //   HMAC Size: 20
 //   HMAC: 415340c7daf824ed684ee586f7b5a67a2febc0d3
 TEST_F(TSIGTest, signUsingHMACSHA1) {
-    tsig::detail::gettimeFunction = testGetTime<0x4dae7d5f>;
+    isc::util::detail::gettimeFunction = testGetTime<0x4dae7d5f>;
 
     secret.clear();
     decodeBase64("MA+QDhXbyqUak+qnMFyTyEirzng=", secret);
@@ -351,7 +350,7 @@ TEST_F(TSIGTest, signUsingHMACSHA1) {
 // Answer: www.example.com. 86400 IN A 192.0.2.1
 // MAC: 8fcda66a7cd1a3b9948eb1869d384a9f
 TEST_F(TSIGTest, signResponse) {
-    tsig::detail::gettimeFunction = testGetTime<0x4da8877a>;
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
 
     ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name,
                                                    tsig_ctx.get());
@@ -386,7 +385,7 @@ TEST_F(TSIGTest, signResponse) {
 //    Answer: example.com. 86400 IN NS ns.example.com.
 //    MAC: 102458f7f62ddd7d638d746034130968
 TEST_F(TSIGTest, signContinuation) {
-    tsig::detail::gettimeFunction = testGetTime<0x4da8e951>;
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8e951>;
 
     const uint16_t axfr_qid = 0x3410;
     const Name zone_name("example.com");
@@ -436,7 +435,7 @@ TEST_F(TSIGTest, signContinuation) {
 //   Error: 0x12 (BADTIME), Other Len: 6
 //   Other data: 00004da8be86
 TEST_F(TSIGTest, badtimeResponse) {
-    tsig::detail::gettimeFunction = testGetTime<0x4da8b9d6>;
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6>;
 
     const uint16_t test_qid = 0x7fc4;
     ConstTSIGRecordPtr tsig = createMessageAndSign(test_qid, test_name,
@@ -445,7 +444,7 @@ TEST_F(TSIGTest, badtimeResponse) {
 
     // "advance the clock" and try validating, which should fail due to BADTIME
     // (verifyTentative actually doesn't check the time, though)
-    tsig::detail::gettimeFunction = testGetTime<0x4da8be86>;
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8be86>;
     tsig_verify_ctx->verifyTentative(tsig, TSIGError::BAD_TIME());
     EXPECT_EQ(TSIGError::BAD_TIME(), tsig_verify_ctx->getError());
 
@@ -469,7 +468,7 @@ TEST_F(TSIGTest, badtimeResponse) {
 }
 
 TEST_F(TSIGTest, badsigResponse) {
-    tsig::detail::gettimeFunction = testGetTime<0x4da8877a>;
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
 
     // Sign a simple message, and force the verification to fail with
     // BADSIG.
@@ -490,7 +489,7 @@ TEST_F(TSIGTest, badsigResponse) {
 
 TEST_F(TSIGTest, badkeyResponse) {
     // A similar test as badsigResponse but for BADKEY
-    tsig::detail::gettimeFunction = testGetTime<0x4da8877a>;
+    isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
     tsig_verify_ctx->verifyTentative(createMessageAndSign(qid, test_name,
                                                           tsig_ctx.get()),
                                      TSIGError::BAD_KEY());

+ 2 - 24
src/lib/dns/tsig.cc

@@ -24,6 +24,7 @@
 #include <exceptions/exceptions.h>
 
 #include <util/buffer.h>
+#include <util/time_utilities.h>
 
 #include <dns/rdataclass.h>
 #include <dns/rrclass.h>
@@ -41,29 +42,6 @@ using namespace isc::dns::rdata;
 
 namespace isc {
 namespace dns {
-
-// Borrowed from dnssectime.cc.  This trick should be unified somewhere.
-namespace tsig {
-namespace detail {
-int64_t (*gettimeFunction)() = NULL;
-}
-}
-
-namespace {
-int64_t
-gettimeofdayWrapper() {
-    using namespace tsig::detail;
-    if (gettimeFunction != NULL) {
-        return (gettimeFunction());
-    }
-
-    struct timeval now;
-    gettimeofday(&now, NULL);
-
-    return (static_cast<int64_t>(now.tv_sec));
-}
-}
-
 namespace {
 typedef boost::shared_ptr<HMAC> HMACPtr;
 }
@@ -107,7 +85,7 @@ TSIGContext::sign(const uint16_t qid, const void* const data,
     }
 
     TSIGError error(TSIGError::NOERROR());
-    const uint64_t now = (gettimeofdayWrapper() & 0x0000ffffffffffffULL);
+    const uint64_t now = (detail::gettimeWrapper() & 0x0000ffffffffffffULL);
 
     // For responses adjust the error code.
     if (impl_->state_ == CHECKED) {

+ 2 - 5
src/lib/util/time_utilities.cc

@@ -110,12 +110,9 @@ timeToText64(uint64_t value) {
 // library, it's not even declared in a header file.
 namespace detail {
 int64_t (*gettimeFunction)() = NULL;
-}
 
-namespace {
 int64_t
-gettimeofdayWrapper() {
-    using namespace detail;
+gettimeWrapper() {
     if (gettimeFunction != NULL) {
         return (gettimeFunction());
     }
@@ -132,7 +129,7 @@ timeToText32(const uint32_t value) {
     // We first adjust the time to the closest epoch based on the current time.
     // Note that the following variables must be signed in order to handle
     // time until year 2038 correctly.
-    const int64_t start = gettimeofdayWrapper() - 0x7fffffff;
+    const int64_t start = detail::gettimeWrapper() - 0x7fffffff;
     int64_t base = 0;
     int64_t t;
     while ((t = (base + value)) < start) {

+ 28 - 0
src/lib/util/time_utilities.h

@@ -15,6 +15,8 @@
 #ifndef __TIME_UTILITIES_H
 #define __TIME_UTILITIES_H 1
 
+#include <string>
+
 #include <sys/types.h>
 #include <stdint.h>
 
@@ -39,6 +41,32 @@ public:
         isc::Exception(file, line, what) {}
 };
 
+namespace detail {
+/// Return the current time in seconds
+///
+/// This function returns the "current" time in seconds from epoch
+/// (00:00:00 January 1, 1970) as a 64-bit signed integer.  The return
+/// value can represent a point of time before epoch as a negative number.
+///
+/// This function is provided to help test time conscious implementations
+/// such as DNSSEC and TSIG signatures.  It is difficult to test them with
+/// an unusual or a specifically chosen "current" via system-provided
+/// library functions to get time.  This function acts as a straightforward
+/// wrapper of such a library function, but provides test code with a hook
+/// to return an arbitrary time value: if \c isc::util::detail::gettimeFunction
+/// is set to a pointer of function that returns 64-bit signed integer,
+/// \c gettimeWrapper() calls that function instead of the system library.
+///
+/// This hook variable is specifically intended for testing purposes, so,
+/// even if it's visible outside of this library, it's not even declared in a
+/// header file.
+///
+/// If the implementation doesn't need to be tested with faked current time,
+/// it should simply use the system supplied library function instead of
+/// this one.
+int64_t gettimeWrapper();
+}
+
 ///
 /// \name DNSSEC time conversion functions.
 ///