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
15namespace net {
16
17class DnsRRResolverTest : public testing::Test {
18};
19
20class 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.
29TEST_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
44TEST_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
60TEST_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.
130static 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
173TEST_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
186TEST_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
195TEST_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