Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/base/dnsrr_resolver.h"
      6 
      7 #include "base/callback.h"
      8 #include "base/synchronization/lock.h"
      9 #include "net/base/dns_util.h"
     10 #include "net/base/net_errors.h"
     11 #include "net/base/net_log.h"
     12 #include "net/base/test_completion_callback.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 
     15 namespace net {
     16 
     17 class DnsRRResolverTest : public testing::Test {
     18 };
     19 
     20 class ExplodingCallback : public CallbackRunner<Tuple1<int> > {
     21  public:
     22   virtual void RunWithParams(const Tuple1<int>& params) {
     23     FAIL();
     24   }
     25 };
     26 
     27 // These tests are disabled because they depend on the external network to
     28 // pass. However, they may be useful when chaging the code.
     29 TEST_F(DnsRRResolverTest, DISABLED_ResolveReal) {
     30   RRResponse response;
     31   TestCompletionCallback callback;
     32   DnsRRResolver resolver;
     33   DnsRRResolver::Handle handle;
     34 
     35   handle = resolver.Resolve("test.imperialviolet.org", 13172, 0,
     36                             &callback, &response, 0, BoundNetLog());
     37   ASSERT_TRUE(handle != DnsRRResolver::kInvalidHandle);
     38   ASSERT_EQ(OK, callback.WaitForResult());
     39   ASSERT_EQ(1u, response.rrdatas.size());
     40   LOG(ERROR) << "result length " << response.rrdatas[0].size();
     41   LOG(ERROR) << "result is " << response.rrdatas[0];
     42 }
     43 
     44 TEST_F(DnsRRResolverTest, DISABLED_ResolveReal2) {
     45   RRResponse response;
     46   TestCompletionCallback callback;
     47   DnsRRResolver resolver;
     48   DnsRRResolver::Handle handle;
     49 
     50   handle = resolver.Resolve("google.com", kDNS_TXT, 0,
     51                             &callback, &response, 0, BoundNetLog());
     52   ASSERT_TRUE(handle != DnsRRResolver::kInvalidHandle);
     53   ASSERT_EQ(OK, callback.WaitForResult());
     54   ASSERT_EQ(1u, response.rrdatas.size());
     55   LOG(ERROR) << "result length " << response.rrdatas[0].size();
     56   LOG(ERROR) << "result is " << response.rrdatas[0];
     57 }
     58 
     59 
     60 TEST_F(DnsRRResolverTest, Resolve) {
     61   RRResponse response;
     62   TestCompletionCallback callback;
     63   DnsRRResolver resolver;
     64   DnsRRResolver::Handle handle;
     65 
     66   handle = resolver.Resolve("www.testing.notatld", kDNS_TESTING, 0,
     67                             &callback, &response, 0, BoundNetLog());
     68   ASSERT_TRUE(handle != DnsRRResolver::kInvalidHandle);
     69   ASSERT_EQ(OK, callback.WaitForResult());
     70   ASSERT_EQ(1u, response.rrdatas.size());
     71   ASSERT_STREQ("goats!", response.rrdatas[0].c_str());
     72   ASSERT_EQ(1u, resolver.requests());
     73   ASSERT_EQ(0u, resolver.cache_hits());
     74   ASSERT_EQ(0u, resolver.inflight_joins());
     75 
     76   // Test a cache hit.
     77   handle = resolver.Resolve("www.testing.notatld", kDNS_TESTING, 0,
     78                             &callback, &response, 0, BoundNetLog());
     79   ASSERT_TRUE(handle != DnsRRResolver::kInvalidHandle);
     80   ASSERT_EQ(OK, callback.WaitForResult());
     81   ASSERT_EQ(1u, response.rrdatas.size());
     82   ASSERT_STREQ("goats!", response.rrdatas[0].c_str());
     83   ASSERT_EQ(2u, resolver.requests());
     84   ASSERT_EQ(1u, resolver.cache_hits());
     85   ASSERT_EQ(0u, resolver.inflight_joins());
     86 
     87   // Test that a callback is never made. This depends on there being another
     88   // test after this one which will pump the MessageLoop.
     89   ExplodingCallback callback3;
     90   handle = resolver.Resolve("www.testing.notatld", kDNS_TESTING, 0,
     91                             &callback3, &response, 0, BoundNetLog());
     92   ASSERT_TRUE(handle != DnsRRResolver::kInvalidHandle);
     93   resolver.CancelResolve(handle);
     94   ASSERT_EQ(3u, resolver.requests());
     95   ASSERT_EQ(2u, resolver.cache_hits());
     96   ASSERT_EQ(0u, resolver.inflight_joins());
     97 
     98   // Test what happens in the event of a network config change.
     99   handle = resolver.Resolve("nx.testing.notatld", kDNS_TESTING, 0,
    100                             &callback, &response, 0, BoundNetLog());
    101   ASSERT_TRUE(handle != DnsRRResolver::kInvalidHandle);
    102   resolver.OnIPAddressChanged();
    103   ASSERT_TRUE(callback.have_result());
    104   ASSERT_EQ(ERR_ABORTED, callback.WaitForResult());
    105   ASSERT_EQ(4u, resolver.requests());
    106   ASSERT_EQ(2u, resolver.cache_hits());
    107   ASSERT_EQ(0u, resolver.inflight_joins());
    108 
    109   // Test an inflight join. (Note that this depends on the cache being flushed
    110   // by OnIPAddressChanged.)
    111   TestCompletionCallback callback2;
    112   DnsRRResolver::Handle handle2;
    113   handle = resolver.Resolve("nx.testing.notatld", kDNS_TESTING, 0,
    114                             &callback, &response, 0, BoundNetLog());
    115   ASSERT_TRUE(handle != DnsRRResolver::kInvalidHandle);
    116   handle2 = resolver.Resolve("nx.testing.notatld", kDNS_TESTING, 0,
    117                              &callback2, &response, 0, BoundNetLog());
    118   ASSERT_TRUE(handle2 != DnsRRResolver::kInvalidHandle);
    119   ASSERT_EQ(ERR_NAME_NOT_RESOLVED, callback.WaitForResult());
    120   ASSERT_EQ(ERR_NAME_NOT_RESOLVED, callback2.WaitForResult());
    121   ASSERT_EQ(6u, resolver.requests());
    122   ASSERT_EQ(2u, resolver.cache_hits());
    123   ASSERT_EQ(1u, resolver.inflight_joins());
    124 }
    125 
    126 #if defined(OS_POSIX)
    127 // This is a DNS packet resulting from querying a recursive resolver for a TXT
    128 // record for agl._pka.imperialviolet.org. You should be able to get a
    129 // replacement from a packet capture should it ever be needed.
    130 static const uint8 kExamplePacket[] = {
    131   0xce, 0xfe, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02, 0x00, 0x06, 0x00, 0x01, 0x03,
    132   0x61, 0x67, 0x6c, 0x04, 0x5f, 0x70, 0x6b, 0x61, 0x0e, 0x69, 0x6d, 0x70, 0x65,
    133   0x72, 0x69, 0x61, 0x6c, 0x76, 0x69, 0x6f, 0x6c, 0x65, 0x74, 0x03, 0x6f, 0x72,
    134   0x67, 0x00, 0x00, 0x10, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x10, 0x00, 0x01, 0x00,
    135   0x00, 0x01, 0x2c, 0x00, 0x5e, 0x5d, 0x76, 0x3d, 0x70, 0x6b, 0x61, 0x31, 0x3b,
    136   0x66, 0x70, 0x72, 0x3d, 0x32, 0x41, 0x46, 0x30, 0x30, 0x33, 0x32, 0x42, 0x34,
    137   0x38, 0x45, 0x38, 0x35, 0x36, 0x43, 0x45, 0x30, 0x36, 0x31, 0x35, 0x37, 0x41,
    138   0x31, 0x41, 0x44, 0x34, 0x33, 0x43, 0x36, 0x37, 0x30, 0x44, 0x45, 0x30, 0x34,
    139   0x41, 0x41, 0x41, 0x37, 0x34, 0x3b, 0x75, 0x72, 0x69, 0x3d, 0x68, 0x74, 0x74,
    140   0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6d, 0x70, 0x65, 0x72,
    141   0x69, 0x61, 0x6c, 0x76, 0x69, 0x6f, 0x6c, 0x65, 0x74, 0x2e, 0x6f, 0x72, 0x67,
    142   0x2f, 0x6b, 0x65, 0x79, 0x2e, 0x61, 0x73, 0x63, 0xc0, 0x0c, 0x00, 0x2e, 0x00,
    143   0x01, 0x00, 0x00, 0x01, 0x2c, 0x00, 0xc6, 0x00, 0x10, 0x05, 0x04, 0x00, 0x01,
    144   0x51, 0x80, 0x4c, 0x74, 0x2f, 0x1a, 0x4c, 0x4c, 0x9c, 0xeb, 0x45, 0xc9, 0x0e,
    145   0x69, 0x6d, 0x70, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x76, 0x69, 0x6f, 0x6c, 0x65,
    146   0x74, 0x03, 0x6f, 0x72, 0x67, 0x00, 0x3b, 0x6d, 0x3d, 0xbb, 0xae, 0x1b, 0x07,
    147   0x8d, 0xa9, 0xb0, 0xa7, 0xa5, 0x7a, 0x84, 0x24, 0x34, 0x29, 0x43, 0x36, 0x3f,
    148   0x5a, 0x48, 0x3b, 0x79, 0xa3, 0x16, 0xa4, 0x28, 0x5b, 0xd7, 0x03, 0xc6, 0x93,
    149   0xba, 0x4e, 0x93, 0x4d, 0x18, 0x5c, 0x98, 0xc2, 0x0d, 0x57, 0xd2, 0x6b, 0x9a,
    150   0x72, 0xbd, 0xe5, 0x8d, 0x10, 0x7b, 0x03, 0xe7, 0x19, 0x1e, 0x51, 0xe5, 0x7e,
    151   0x49, 0x6b, 0xa3, 0xa8, 0xf1, 0xd3, 0x1b, 0xff, 0x40, 0x26, 0x82, 0x65, 0xd0,
    152   0x74, 0x8e, 0xcf, 0xc9, 0x71, 0xea, 0x91, 0x57, 0x7e, 0x50, 0x61, 0x4d, 0x4b,
    153   0x77, 0x05, 0x6a, 0xd8, 0x3f, 0x12, 0x87, 0x50, 0xc2, 0x35, 0x13, 0xab, 0x01,
    154   0x78, 0xd2, 0x3a, 0x55, 0xa2, 0x89, 0xc8, 0x87, 0xe2, 0x7b, 0xec, 0x51, 0x7c,
    155   0xc0, 0x24, 0xb5, 0xa3, 0x33, 0x78, 0x98, 0x28, 0x8e, 0x9b, 0x6b, 0x88, 0x13,
    156   0x25, 0xfa, 0x1d, 0xdc, 0xf1, 0xf0, 0xa6, 0x8d, 0x2a, 0xbb, 0xbc, 0xb0, 0xc7,
    157   0x97, 0x98, 0x8e, 0xef, 0xd9, 0x12, 0x24, 0xee, 0x38, 0x50, 0xdb, 0xd3, 0x59,
    158   0xcc, 0x30, 0x54, 0x4c, 0x38, 0x94, 0x24, 0xbc, 0x75, 0xa5, 0xc0, 0xc4, 0x00,
    159   0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x15, 0x02, 0x62, 0x30, 0x03,
    160   0x6f, 0x72, 0x67, 0x0b, 0x61, 0x66, 0x69, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x6e,
    161   0x73, 0x74, 0xc0, 0xc4, 0xc0, 0xc4, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
    162   0x3a, 0x00, 0x19, 0x02, 0x63, 0x30, 0x03, 0x6f, 0x72, 0x67, 0x0b, 0x61, 0x66,
    163   0x69, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x6e, 0x73, 0x74, 0x04, 0x69, 0x6e, 0x66,
    164   0x6f, 0x00, 0xc0, 0xc4, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3a, 0x00,
    165   0x05, 0x02, 0x61, 0x30, 0xc1, 0x99, 0xc0, 0xc4, 0x00, 0x02, 0x00, 0x01, 0x00,
    166   0x00, 0x00, 0x3a, 0x00, 0x05, 0x02, 0x62, 0x32, 0xc1, 0x78, 0xc0, 0xc4, 0x00,
    167   0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x05, 0x02, 0x64, 0x30, 0xc1,
    168   0x78, 0xc0, 0xc4, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x05,
    169   0x02, 0x61, 0x32, 0xc1, 0x99, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x80,
    170   0x00, 0x00, 0x00,
    171 };
    172 
    173 TEST_F(DnsRRResolverTest, ParseExample) {
    174   RRResponse response;
    175   ASSERT_TRUE(response.ParseFromResponse(kExamplePacket,
    176               sizeof(kExamplePacket), kDNS_TXT));
    177   ASSERT_EQ(1u, response.rrdatas.size());
    178   ASSERT_EQ(1u, response.signatures.size());
    179   ASSERT_STREQ("agl._pka.imperialviolet.org", response.name.c_str());
    180   ASSERT_STREQ("]v=pka1;fpr=2AF0032B48E856CE06157A1AD43C670DE04AAA74;"
    181                "uri=http://www.imperialviolet.org/key.asc",
    182                response.rrdatas[0].c_str());
    183   ASSERT_FALSE(response.dnssec);
    184 }
    185 
    186 TEST_F(DnsRRResolverTest, FuzzTruncation) {
    187   RRResponse response;
    188 
    189   for (unsigned len = sizeof(kExamplePacket); len <= sizeof(kExamplePacket);
    190        len--) {
    191     response.ParseFromResponse(kExamplePacket, len, kDNS_TXT);
    192   }
    193 }
    194 
    195 TEST_F(DnsRRResolverTest, FuzzCorruption) {
    196   RRResponse response;
    197   uint8 copy[sizeof(kExamplePacket)];
    198 
    199 
    200   for (unsigned bit_to_corrupt = 0; bit_to_corrupt < sizeof(kExamplePacket) * 8;
    201        bit_to_corrupt++) {
    202     unsigned byte = bit_to_corrupt >> 3;
    203     unsigned bit = bit_to_corrupt & 7;
    204 
    205     memcpy(copy, kExamplePacket, sizeof(copy));
    206     copy[byte] ^= (1 << bit);
    207 
    208     response.ParseFromResponse(copy, sizeof(copy), kDNS_TXT);
    209   }
    210 }
    211 #endif
    212 
    213 }  // namespace net
    214