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:
RunWithParams(const Tuple1<int> & params)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.
TEST_F(DnsRRResolverTest,DISABLED_ResolveReal)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
TEST_F(DnsRRResolverTest,DISABLED_ResolveReal2)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
TEST_F(DnsRRResolverTest,Resolve)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
TEST_F(DnsRRResolverTest,ParseExample)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
TEST_F(DnsRRResolverTest,FuzzTruncation)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
TEST_F(DnsRRResolverTest,FuzzCorruption)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