1 // Copyright 2012 The Chromium Authors
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/dns/mapped_host_resolver.h"
6
7 #include <memory>
8 #include <optional>
9 #include <utility>
10
11 #include "base/test/task_environment.h"
12 #include "net/base/address_list.h"
13 #include "net/base/ip_address.h"
14 #include "net/base/ip_endpoint.h"
15 #include "net/base/net_errors.h"
16 #include "net/base/network_isolation_key.h"
17 #include "net/base/test_completion_callback.h"
18 #include "net/dns/mock_host_resolver.h"
19 #include "net/log/net_log_with_source.h"
20 #include "net/test/gtest_util.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "url/scheme_host_port.h"
24 #include "url/url_constants.h"
25
26 using net::test::IsError;
27 using net::test::IsOk;
28
29 namespace net {
30
31 namespace {
32
FirstAddress(const AddressList & address_list)33 std::string FirstAddress(const AddressList& address_list) {
34 if (address_list.empty())
35 return std::string();
36 return address_list.front().ToString();
37 }
38
TEST(MappedHostResolverTest,Inclusion)39 TEST(MappedHostResolverTest, Inclusion) {
40 base::test::TaskEnvironment task_environment;
41
42 // Create a mock host resolver, with specific hostname to IP mappings.
43 auto resolver_impl = std::make_unique<MockHostResolver>();
44 resolver_impl->rules()->AddSimulatedFailure("*google.com");
45 resolver_impl->rules()->AddRule("baz.com", "192.168.1.5");
46 resolver_impl->rules()->AddRule("foo.com", "192.168.1.8");
47 resolver_impl->rules()->AddRule("proxy", "192.168.1.11");
48
49 // Create a remapped resolver that uses |resolver_impl|.
50 auto resolver =
51 std::make_unique<MappedHostResolver>(std::move(resolver_impl));
52
53 // Try resolving "www.google.com:80". There are no mappings yet, so this
54 // hits |resolver_impl| and fails.
55 TestCompletionCallback callback;
56 std::unique_ptr<HostResolver::ResolveHostRequest> request =
57 resolver->CreateRequest(HostPortPair("www.google.com", 80),
58 NetworkAnonymizationKey(), NetLogWithSource(),
59 std::nullopt);
60 int rv = request->Start(callback.callback());
61 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
62 rv = callback.WaitForResult();
63 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
64 EXPECT_FALSE(request->GetAddressResults());
65
66 // Remap *.google.com to baz.com.
67 EXPECT_TRUE(resolver->AddRuleFromString("map *.google.com baz.com"));
68 request.reset();
69
70 // Try resolving "www.google.com:80". Should be remapped to "baz.com:80".
71 request = resolver->CreateRequest(HostPortPair("www.google.com", 80),
72 NetworkAnonymizationKey(),
73 NetLogWithSource(), std::nullopt);
74 rv = request->Start(callback.callback());
75 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
76 rv = callback.WaitForResult();
77 EXPECT_THAT(rv, IsOk());
78 EXPECT_EQ("192.168.1.5:80", FirstAddress(*request->GetAddressResults()));
79 request.reset();
80
81 // Try resolving "foo.com:77". This will NOT be remapped, so result
82 // is "foo.com:77".
83 request = resolver->CreateRequest(HostPortPair("foo.com", 77),
84 NetworkAnonymizationKey(),
85 NetLogWithSource(), std::nullopt);
86 rv = request->Start(callback.callback());
87 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
88 rv = callback.WaitForResult();
89 EXPECT_THAT(rv, IsOk());
90 EXPECT_EQ("192.168.1.8:77", FirstAddress(*request->GetAddressResults()));
91 request.reset();
92
93 // Remap "*.org" to "proxy:99".
94 EXPECT_TRUE(resolver->AddRuleFromString("Map *.org proxy:99"));
95
96 // Try resolving "chromium.org:61". Should be remapped to "proxy:99".
97 request = resolver->CreateRequest(HostPortPair("chromium.org", 61),
98 NetworkAnonymizationKey(),
99 NetLogWithSource(), std::nullopt);
100 rv = request->Start(callback.callback());
101 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
102 rv = callback.WaitForResult();
103 EXPECT_THAT(rv, IsOk());
104 EXPECT_EQ("192.168.1.11:99", FirstAddress(*request->GetAddressResults()));
105 }
106
TEST(MappedHostResolverTest,MapsHostWithScheme)107 TEST(MappedHostResolverTest, MapsHostWithScheme) {
108 base::test::TaskEnvironment task_environment;
109
110 // Create a mock host resolver, with specific hostname to IP mappings.
111 auto resolver_impl = std::make_unique<MockHostResolver>();
112 resolver_impl->rules()->AddRule("remapped.test", "192.168.1.22");
113
114 // Create a remapped resolver that uses `resolver_impl`.
115 auto resolver =
116 std::make_unique<MappedHostResolver>(std::move(resolver_impl));
117 ASSERT_TRUE(resolver->AddRuleFromString("MAP to.map.test remapped.test"));
118
119 std::unique_ptr<HostResolver::ResolveHostRequest> request =
120 resolver->CreateRequest(
121 url::SchemeHostPort(url::kHttpScheme, "to.map.test", 155),
122 NetworkAnonymizationKey(), NetLogWithSource(), std::nullopt);
123
124 TestCompletionCallback callback;
125 int rv = request->Start(callback.callback());
126
127 EXPECT_THAT(callback.GetResult(rv), IsOk());
128 EXPECT_THAT(
129 request->GetAddressResults()->endpoints(),
130 testing::ElementsAre(IPEndPoint(IPAddress(192, 168, 1, 22), 155)));
131 }
132
TEST(MappedHostResolverTest,MapsHostWithSchemeToIpLiteral)133 TEST(MappedHostResolverTest, MapsHostWithSchemeToIpLiteral) {
134 base::test::TaskEnvironment task_environment;
135
136 // Create a mock host resolver, with specific hostname to IP mappings.
137 auto resolver_impl = std::make_unique<MockHostResolver>();
138 resolver_impl->rules()->AddRule("host.test", "192.168.1.22");
139
140 // Create a remapped resolver that uses `resolver_impl`.
141 auto resolver =
142 std::make_unique<MappedHostResolver>(std::move(resolver_impl));
143 ASSERT_TRUE(resolver->AddRuleFromString("MAP host.test [1234:5678::000A]"));
144
145 IPAddress expected_address;
146 ASSERT_TRUE(expected_address.AssignFromIPLiteral("1234:5678::000A"));
147
148 std::unique_ptr<HostResolver::ResolveHostRequest> request =
149 resolver->CreateRequest(
150 url::SchemeHostPort(url::kHttpScheme, "host.test", 156),
151 NetworkAnonymizationKey(), NetLogWithSource(), std::nullopt);
152
153 TestCompletionCallback callback;
154 int rv = request->Start(callback.callback());
155
156 EXPECT_THAT(callback.GetResult(rv), IsOk());
157 EXPECT_THAT(request->GetAddressResults()->endpoints(),
158 testing::ElementsAre(IPEndPoint(expected_address, 156)));
159 }
160
161 // Tests that remapped URL gets canonicalized when passing scheme.
TEST(MappedHostResolverTest,MapsHostWithSchemeToNonCanon)162 TEST(MappedHostResolverTest, MapsHostWithSchemeToNonCanon) {
163 base::test::TaskEnvironment task_environment;
164
165 // Create a mock host resolver, with specific hostname to IP mappings.
166 auto resolver_impl = std::make_unique<MockHostResolver>();
167 resolver_impl->rules()->AddRule("remapped.test", "192.168.1.23");
168
169 // Create a remapped resolver that uses `resolver_impl`.
170 auto resolver =
171 std::make_unique<MappedHostResolver>(std::move(resolver_impl));
172 ASSERT_TRUE(resolver->AddRuleFromString("MAP host.test reMapped.TEST"));
173
174 std::unique_ptr<HostResolver::ResolveHostRequest> request =
175 resolver->CreateRequest(
176 url::SchemeHostPort(url::kHttpScheme, "host.test", 157),
177 NetworkAnonymizationKey(), NetLogWithSource(), std::nullopt);
178
179 TestCompletionCallback callback;
180 int rv = request->Start(callback.callback());
181
182 EXPECT_THAT(callback.GetResult(rv), IsOk());
183 EXPECT_THAT(
184 request->GetAddressResults()->endpoints(),
185 testing::ElementsAre(IPEndPoint(IPAddress(192, 168, 1, 23), 157)));
186 }
187
TEST(MappedHostResolverTest,MapsHostWithSchemeToNameWithPort)188 TEST(MappedHostResolverTest, MapsHostWithSchemeToNameWithPort) {
189 base::test::TaskEnvironment task_environment;
190
191 // Create a mock host resolver, with specific hostname to IP mappings.
192 auto resolver_impl = std::make_unique<MockHostResolver>();
193 resolver_impl->rules()->AddRule("remapped.test", "192.168.1.24");
194
195 // Create a remapped resolver that uses `resolver_impl`.
196 auto resolver =
197 std::make_unique<MappedHostResolver>(std::move(resolver_impl));
198 ASSERT_TRUE(resolver->AddRuleFromString("MAP host.test remapped.test:258"));
199
200 std::unique_ptr<HostResolver::ResolveHostRequest> request =
201 resolver->CreateRequest(
202 url::SchemeHostPort(url::kHttpScheme, "host.test", 158),
203 NetworkAnonymizationKey(), NetLogWithSource(), std::nullopt);
204
205 TestCompletionCallback callback;
206 int rv = request->Start(callback.callback());
207
208 EXPECT_THAT(callback.GetResult(rv), IsOk());
209 EXPECT_THAT(
210 request->GetAddressResults()->endpoints(),
211 testing::ElementsAre(IPEndPoint(IPAddress(192, 168, 1, 24), 258)));
212 }
213
TEST(MappedHostResolverTest,HandlesUnmappedHostWithScheme)214 TEST(MappedHostResolverTest, HandlesUnmappedHostWithScheme) {
215 base::test::TaskEnvironment task_environment;
216
217 // Create a mock host resolver, with specific hostname to IP mappings.
218 auto resolver_impl = std::make_unique<MockHostResolver>();
219 resolver_impl->rules()->AddRule("unmapped.test", "192.168.1.23");
220
221 // Create a remapped resolver that uses `resolver_impl`.
222 auto resolver =
223 std::make_unique<MappedHostResolver>(std::move(resolver_impl));
224
225 std::unique_ptr<HostResolver::ResolveHostRequest> request =
226 resolver->CreateRequest(
227 url::SchemeHostPort(url::kHttpsScheme, "unmapped.test", 155),
228 NetworkAnonymizationKey(), NetLogWithSource(), std::nullopt);
229
230 TestCompletionCallback callback;
231 int rv = request->Start(callback.callback());
232
233 EXPECT_THAT(callback.GetResult(rv), IsOk());
234 EXPECT_THAT(
235 request->GetAddressResults()->endpoints(),
236 testing::ElementsAre(IPEndPoint(IPAddress(192, 168, 1, 23), 155)));
237 }
238
239 // Tests that exclusions are respected.
TEST(MappedHostResolverTest,Exclusion)240 TEST(MappedHostResolverTest, Exclusion) {
241 base::test::TaskEnvironment task_environment;
242
243 // Create a mock host resolver, with specific hostname to IP mappings.
244 auto resolver_impl = std::make_unique<MockHostResolver>();
245 resolver_impl->rules()->AddRule("baz", "192.168.1.5");
246 resolver_impl->rules()->AddRule("www.google.com", "192.168.1.3");
247
248 // Create a remapped resolver that uses |resolver_impl|.
249 auto resolver =
250 std::make_unique<MappedHostResolver>(std::move(resolver_impl));
251
252 TestCompletionCallback callback;
253
254 // Remap "*.com" to "baz".
255 EXPECT_TRUE(resolver->AddRuleFromString("map *.com baz"));
256
257 // Add an exclusion for "*.google.com".
258 EXPECT_TRUE(resolver->AddRuleFromString("EXCLUDE *.google.com"));
259
260 // Try resolving "www.google.com". Should not be remapped due to exclusion).
261 std::unique_ptr<HostResolver::ResolveHostRequest> request =
262 resolver->CreateRequest(HostPortPair("www.google.com", 80),
263 NetworkAnonymizationKey(), NetLogWithSource(),
264 std::nullopt);
265 int rv = request->Start(callback.callback());
266 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
267 rv = callback.WaitForResult();
268 EXPECT_THAT(rv, IsOk());
269 EXPECT_EQ("192.168.1.3:80", FirstAddress(*request->GetAddressResults()));
270 request.reset();
271
272 // Try resolving "chrome.com:80". Should be remapped to "baz:80".
273 request = resolver->CreateRequest(HostPortPair("chrome.com", 80),
274 NetworkAnonymizationKey(),
275 NetLogWithSource(), std::nullopt);
276 rv = request->Start(callback.callback());
277 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
278 rv = callback.WaitForResult();
279 EXPECT_THAT(rv, IsOk());
280 EXPECT_EQ("192.168.1.5:80", FirstAddress(*request->GetAddressResults()));
281 }
282
TEST(MappedHostResolverTest,SetRulesFromString)283 TEST(MappedHostResolverTest, SetRulesFromString) {
284 base::test::TaskEnvironment task_environment;
285
286 // Create a mock host resolver, with specific hostname to IP mappings.
287 auto resolver_impl = std::make_unique<MockHostResolver>();
288 resolver_impl->rules()->AddRule("baz", "192.168.1.7");
289 resolver_impl->rules()->AddRule("bar", "192.168.1.9");
290
291 // Create a remapped resolver that uses |resolver_impl|.
292 auto resolver =
293 std::make_unique<MappedHostResolver>(std::move(resolver_impl));
294
295 TestCompletionCallback callback;
296
297 // Remap "*.com" to "baz", and *.net to "bar:60".
298 resolver->SetRulesFromString("map *.com baz , map *.net bar:60");
299
300 // Try resolving "www.google.com". Should be remapped to "baz".
301 std::unique_ptr<HostResolver::ResolveHostRequest> request =
302 resolver->CreateRequest(HostPortPair("www.google.com", 80),
303 NetworkAnonymizationKey(), NetLogWithSource(),
304 std::nullopt);
305 int rv = request->Start(callback.callback());
306 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
307 rv = callback.WaitForResult();
308 EXPECT_THAT(rv, IsOk());
309 EXPECT_EQ("192.168.1.7:80", FirstAddress(*request->GetAddressResults()));
310 request.reset();
311
312 // Try resolving "chrome.net:80". Should be remapped to "bar:60".
313 request = resolver->CreateRequest(HostPortPair("chrome.net", 80),
314 NetworkAnonymizationKey(),
315 NetLogWithSource(), std::nullopt);
316 rv = request->Start(callback.callback());
317 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
318 rv = callback.WaitForResult();
319 EXPECT_THAT(rv, IsOk());
320 EXPECT_EQ("192.168.1.9:60", FirstAddress(*request->GetAddressResults()));
321 }
322
323 // Parsing bad rules should silently discard the rule (and never crash).
TEST(MappedHostResolverTest,ParseInvalidRules)324 TEST(MappedHostResolverTest, ParseInvalidRules) {
325 base::test::TaskEnvironment task_environment;
326
327 auto resolver =
328 std::make_unique<MappedHostResolver>(std::unique_ptr<HostResolver>());
329
330 EXPECT_FALSE(resolver->AddRuleFromString("xyz"));
331 EXPECT_FALSE(resolver->AddRuleFromString(std::string()));
332 EXPECT_FALSE(resolver->AddRuleFromString(" "));
333 EXPECT_FALSE(resolver->AddRuleFromString("EXCLUDE"));
334 EXPECT_FALSE(resolver->AddRuleFromString("EXCLUDE foo bar"));
335 EXPECT_FALSE(resolver->AddRuleFromString("INCLUDE"));
336 EXPECT_FALSE(resolver->AddRuleFromString("INCLUDE x"));
337 EXPECT_FALSE(resolver->AddRuleFromString("INCLUDE x :10"));
338 }
339
340 // Test mapping hostnames to resolving failures.
TEST(MappedHostResolverTest,MapToError)341 TEST(MappedHostResolverTest, MapToError) {
342 base::test::TaskEnvironment task_environment;
343
344 // Outstanding request.
345 auto resolver_impl = std::make_unique<MockHostResolver>();
346 resolver_impl->rules()->AddRule("*", "192.168.1.5");
347
348 auto resolver =
349 std::make_unique<MappedHostResolver>(std::move(resolver_impl));
350
351 // Remap *.google.com to resolving failures.
352 EXPECT_TRUE(resolver->AddRuleFromString("MAP *.google.com ^NOTFOUND"));
353
354 // Try resolving www.google.com --> Should give an error.
355 TestCompletionCallback callback1;
356 std::unique_ptr<HostResolver::ResolveHostRequest> request =
357 resolver->CreateRequest(HostPortPair("www.google.com", 80),
358 NetworkAnonymizationKey(), NetLogWithSource(),
359 std::nullopt);
360 int rv = request->Start(callback1.callback());
361 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
362 request.reset();
363
364 // Try resolving www.foo.com --> Should succeed.
365 TestCompletionCallback callback2;
366 request = resolver->CreateRequest(HostPortPair("www.foo.com", 80),
367 NetworkAnonymizationKey(),
368 NetLogWithSource(), std::nullopt);
369 rv = request->Start(callback2.callback());
370 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
371 rv = callback2.WaitForResult();
372 EXPECT_THAT(rv, IsOk());
373 EXPECT_EQ("192.168.1.5:80", FirstAddress(*request->GetAddressResults()));
374 }
375
TEST(MappedHostResolverTest,MapHostWithSchemeToError)376 TEST(MappedHostResolverTest, MapHostWithSchemeToError) {
377 base::test::TaskEnvironment task_environment;
378
379 // Create a mock host resolver, with specific hostname to IP mappings.
380 auto resolver_impl = std::make_unique<MockHostResolver>();
381 resolver_impl->rules()->AddRule("host.test", "192.168.1.25");
382
383 // Create a remapped resolver that uses `resolver_impl`.
384 auto resolver =
385 std::make_unique<MappedHostResolver>(std::move(resolver_impl));
386 ASSERT_TRUE(resolver->AddRuleFromString("MAP host.test ^NOTFOUND"));
387
388 std::unique_ptr<HostResolver::ResolveHostRequest> request =
389 resolver->CreateRequest(
390 url::SchemeHostPort(url::kWssScheme, "host.test", 155),
391 NetworkAnonymizationKey(), NetLogWithSource(), std::nullopt);
392
393 TestCompletionCallback callback;
394 int rv = request->Start(callback.callback());
395 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
396 }
397
398 } // namespace
399
400 } // namespace net
401