xref: /aosp_15_r20/external/cronet/net/dns/mapped_host_resolver_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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