blob: 7efd5f24c4616336b0ec5db7fba0063684c73832 [file] [log] [blame]
[email protected]78eac2a2012-03-14 19:09:271// Copyright (c) 2012 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/dns/dns_test_util.h"
6
Eric Orth3b26e3ba2020-11-12 22:43:137#include <string>
8#include <utility>
9#include <vector>
10
[email protected]d9806a972014-02-26 18:14:5711#include "base/big_endian.h"
[email protected]78eac2a2012-03-14 19:09:2712#include "base/bind.h"
Eric Orth3b26e3ba2020-11-12 22:43:1313#include "base/check.h"
skyostil4891b25b2015-06-11 11:43:4514#include "base/location.h"
Eric Orth828bd3ae2018-12-12 17:30:3615#include "base/numerics/safe_conversions.h"
Benjamin M. Schwartz571353c22021-12-13 16:41:1116#include "base/ranges/algorithm.h"
Eric Orthac9aafb2021-07-29 23:03:4317#include "base/stl_util.h"
Dan McArdle00271b92022-02-11 23:41:1818#include "base/strings/strcat.h"
[email protected]78eac2a2012-03-14 19:09:2719#include "base/sys_byteorder.h"
Patrick Monette643cdf62021-10-15 19:13:4220#include "base/task/single_thread_task_runner.h"
gabf767595f2016-05-11 18:50:3521#include "base/threading/thread_task_runner_handle.h"
Eric Orth3b26e3ba2020-11-12 22:43:1322#include "base/time/time.h"
Benjamin M. Schwartz6f719eb2021-12-15 17:47:2823#include "net/base/address_list.h"
[email protected]78eac2a2012-03-14 19:09:2724#include "net/base/io_buffer.h"
Eric Orth828bd3ae2018-12-12 17:30:3625#include "net/base/ip_address.h"
Eric Orth48b1b7c2022-01-21 00:21:1626#include "net/base/ip_endpoint.h"
[email protected]78eac2a2012-03-14 19:09:2727#include "net/base/net_errors.h"
[email protected]0adcb2b2012-08-15 21:30:4628#include "net/dns/address_sorter.h"
Eric Orth394db1732019-08-27 20:09:3929#include "net/dns/dns_hosts.h"
[email protected]78eac2a2012-03-14 19:09:2730#include "net/dns/dns_query.h"
Eric Orthaf82b49a2020-02-01 01:48:5031#include "net/dns/dns_session.h"
Eric Orth9300cc62020-08-21 00:29:3432#include "net/dns/dns_socket_allocator.h"
tfarina77021d62015-10-11 20:19:0333#include "net/dns/dns_util.h"
Benjamin M. Schwartz571353c22021-12-13 16:41:1134#include "net/dns/public/dns_over_https_server_config.h"
Eric Orth069a3c6e2020-01-31 23:14:2435#include "net/dns/resolve_context.h"
Benjamin M. Schwartz6f719eb2021-12-15 17:47:2836#include "testing/gmock/include/gmock/gmock-matchers.h"
[email protected]78eac2a2012-03-14 19:09:2737#include "testing/gtest/include/gtest/gtest.h"
Benjamin M. Schwartz6f719eb2021-12-15 17:47:2838#include "url/scheme_host_port.h"
[email protected]78eac2a2012-03-14 19:09:2739
40namespace net {
41namespace {
42
Eric Orth828bd3ae2018-12-12 17:30:3643const uint8_t kMalformedResponseHeader[] = {
44 // Header
45 0x00, 0x14, // Arbitrary ID
46 0x81, 0x80, // Standard query response, RA, no error
47 0x00, 0x01, // 1 question
48 0x00, 0x01, // 1 RR (answers)
49 0x00, 0x00, // 0 authority RRs
50 0x00, 0x00, // 0 additional RRs
51};
52
53// Create a response containing a valid question (as would normally be validated
54// in DnsTransaction) but completely missing a header-declared answer.
Eric Ortha97f0f72020-10-16 16:10:3255DnsResponse CreateMalformedResponse(std::string hostname, uint16_t type) {
Eric Orth828bd3ae2018-12-12 17:30:3656 std::string dns_name;
57 CHECK(DNSDomainFromDot(hostname, &dns_name));
58 DnsQuery query(0x14 /* id */, dns_name, type);
59
60 // Build response to simulate the barebones validation DnsResponse applies to
61 // responses received from the network.
62 auto buffer = base::MakeRefCounted<IOBufferWithSize>(
63 sizeof(kMalformedResponseHeader) + query.question().size());
64 memcpy(buffer->data(), kMalformedResponseHeader,
65 sizeof(kMalformedResponseHeader));
66 memcpy(buffer->data() + sizeof(kMalformedResponseHeader),
67 query.question().data(), query.question().size());
68
Eric Ortha97f0f72020-10-16 16:10:3269 DnsResponse response(buffer, buffer->size());
70 CHECK(response.InitParseWithoutQuery(buffer->size()));
Eric Orth828bd3ae2018-12-12 17:30:3671
72 return response;
73}
74
[email protected]daae1322013-09-05 18:26:5075class MockAddressSorter : public AddressSorter {
76 public:
Chris Watkins68b15032017-12-01 03:07:1377 ~MockAddressSorter() override = default;
Eric Orth48b1b7c2022-01-21 00:21:1678 void Sort(const std::vector<IPEndPoint>& endpoints,
79 CallbackType callback) const override {
[email protected]daae1322013-09-05 18:26:5080 // Do nothing.
Eric Orth48b1b7c2022-01-21 00:21:1681 std::move(callback).Run(true, endpoints);
[email protected]daae1322013-09-05 18:26:5082 }
83};
84
[email protected]daae1322013-09-05 18:26:5085} // namespace
[email protected]78eac2a2012-03-14 19:09:2786
Eric Orth8539e492020-10-19 20:09:5587DnsResourceRecord BuildTestDnsRecord(std::string name,
88 uint16_t type,
89 std::string rdata,
90 base::TimeDelta ttl) {
David Van Cleve34c74c72019-10-31 19:58:0191 DCHECK(!name.empty());
David Van Cleve34c74c72019-10-31 19:58:0192
93 DnsResourceRecord record;
94 record.name = std::move(name);
Eric Orth8539e492020-10-19 20:09:5595 record.type = type;
David Van Cleve34c74c72019-10-31 19:58:0196 record.klass = dns_protocol::kClassIN;
Eric Orth8539e492020-10-19 20:09:5597 record.ttl = ttl.InSeconds();
Eric Orth5d21f152020-10-21 19:15:4398
99 if (!rdata.empty())
100 record.SetOwnedRdata(std::move(rdata));
David Van Cleve34c74c72019-10-31 19:58:01101
102 return record;
103}
104
Eric Orth65fd3e32020-11-18 04:59:17105DnsResourceRecord BuildTestCnameRecord(std::string name,
106 base::StringPiece canonical_name,
107 base::TimeDelta ttl) {
108 DCHECK(!name.empty());
109 DCHECK(!canonical_name.empty());
110
111 std::string rdata;
112 CHECK(DNSDomainFromDot(canonical_name, &rdata));
113
114 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeCNAME,
115 std::move(rdata), ttl);
116}
117
Eric Orth8539e492020-10-19 20:09:55118DnsResourceRecord BuildTestAddressRecord(std::string name,
119 const IPAddress& ip,
120 base::TimeDelta ttl) {
121 DCHECK(!name.empty());
Eric Orth828bd3ae2018-12-12 17:30:36122 DCHECK(ip.IsValid());
123
Eric Orth8539e492020-10-19 20:09:55124 return BuildTestDnsRecord(
125 std::move(name),
126 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA,
127 net::IPAddressToPackedString(ip), ttl);
128}
129
Eric Orth3b26e3ba2020-11-12 22:43:13130DnsResourceRecord BuildTestTextRecord(std::string name,
131 std::vector<std::string> text_strings,
132 base::TimeDelta ttl) {
133 DCHECK(!text_strings.empty());
134
135 std::string rdata;
136 for (const std::string& text_string : text_strings) {
137 DCHECK(!text_string.empty());
138
139 rdata += base::checked_cast<unsigned char>(text_string.size());
140 rdata += text_string;
141 }
142
143 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeTXT,
Eric Orthd16fee6b2020-11-18 06:43:14144 std::move(rdata), ttl);
Eric Orth3b26e3ba2020-11-12 22:43:13145}
146
Eric Orth7139e0552020-11-04 02:41:11147DnsResourceRecord BuildTestHttpsAliasRecord(std::string name,
148 base::StringPiece alias_name,
149 base::TimeDelta ttl) {
150 DCHECK(!name.empty());
151
152 std::string rdata("\000\000", 2);
153
154 std::string alias_domain;
155 CHECK(DNSDomainFromDot(alias_name, &alias_domain));
156 rdata.append(alias_domain);
157
158 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeHttps,
159 std::move(rdata), ttl);
160}
161
162DnsResourceRecord BuildTestHttpsServiceRecord(
163 std::string name,
164 uint16_t priority,
165 base::StringPiece service_name,
166 const std::map<uint16_t, std::string>& params,
167 base::TimeDelta ttl) {
168 DCHECK(!name.empty());
169 DCHECK_NE(priority, 0);
170
171 std::string rdata;
172
173 char num_buffer[2];
174 base::WriteBigEndian(num_buffer, priority);
175 rdata.append(num_buffer, 2);
176
177 std::string service_domain;
Eric Orthac9aafb2021-07-29 23:03:43178 if (service_name == ".") {
179 // HTTPS records have special behavior for `service_name == "."` (that it
180 // will be treated as if the service name is the same as the record owner
181 // name), so allow such inputs despite normally being disallowed for
182 // Chrome-encoded DNS names.
183 service_domain = '\x00';
184 } else {
185 CHECK(DNSDomainFromDot(service_name, &service_domain));
186 }
Eric Orth7139e0552020-11-04 02:41:11187 rdata.append(service_domain);
188
189 for (auto& param : params) {
190 base::WriteBigEndian(num_buffer, param.first);
191 rdata.append(num_buffer, 2);
192
193 base::WriteBigEndian(num_buffer,
194 base::checked_cast<uint16_t>(param.second.size()));
195 rdata.append(num_buffer, 2);
196
197 rdata.append(param.second);
198 }
199
200 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeHttps,
201 std::move(rdata), ttl);
202}
203
Eric Orth8539e492020-10-19 20:09:55204DnsResponse BuildTestDnsResponse(
205 std::string name,
206 uint16_t type,
Eric Orth69c25992020-11-10 16:55:12207 const std::vector<DnsResourceRecord>& answers,
208 const std::vector<DnsResourceRecord>& authority,
Eric Orth9cec76f2020-11-17 07:42:42209 const std::vector<DnsResourceRecord>& additional,
210 uint8_t rcode) {
Eric Orth8539e492020-10-19 20:09:55211 DCHECK(!name.empty());
212
Eric Orth828bd3ae2018-12-12 17:30:36213 std::string dns_name;
214 CHECK(DNSDomainFromDot(name, &dns_name));
Eric Orth8539e492020-10-19 20:09:55215
Anton Bikineev068d2912021-05-15 20:43:52216 absl::optional<DnsQuery> query(absl::in_place, 0, std::move(dns_name), type);
Eric Orth8539e492020-10-19 20:09:55217 return DnsResponse(0, true /* is_authoritative */, answers,
Eric Orth69c25992020-11-10 16:55:12218 authority /* authority_records */,
Eric Orth9cec76f2020-11-17 07:42:42219 additional /* additional_records */, query, rcode,
Eric Orthd16fee6b2020-11-18 06:43:14220 false /* validate_records */);
Eric Orth828bd3ae2018-12-12 17:30:36221}
222
Eric Orth8539e492020-10-19 20:09:55223DnsResponse BuildTestDnsAddressResponse(std::string name,
224 const IPAddress& ip,
225 std::string answer_name) {
226 DCHECK(ip.IsValid());
227
228 if (answer_name.empty())
229 answer_name = name;
230
231 std::vector<DnsResourceRecord> answers = {
232 BuildTestAddressRecord(std::move(answer_name), ip)};
233
234 return BuildTestDnsResponse(
235 std::move(name),
236 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA, answers);
237}
238
Eric Ortha97f0f72020-10-16 16:10:32239DnsResponse BuildTestDnsAddressResponseWithCname(std::string name,
240 const IPAddress& ip,
Eric Orth8539e492020-10-19 20:09:55241 std::string cannonname,
242 std::string answer_name) {
Eric Orth828bd3ae2018-12-12 17:30:36243 DCHECK(ip.IsValid());
244 DCHECK(!cannonname.empty());
245
Eric Orth8539e492020-10-19 20:09:55246 if (answer_name.empty())
247 answer_name = name;
248
249 std::string cname_rdata;
250 CHECK(DNSDomainFromDot(cannonname, &cname_rdata));
251
Eric Orth828bd3ae2018-12-12 17:30:36252 std::vector<DnsResourceRecord> answers = {
Eric Orth8539e492020-10-19 20:09:55253 BuildTestDnsRecord(std::move(answer_name), dns_protocol::kTypeCNAME,
254 std::move(cname_rdata)),
255 BuildTestAddressRecord(std::move(cannonname), ip)};
256
257 return BuildTestDnsResponse(
258 std::move(name),
259 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA, answers);
Eric Orth828bd3ae2018-12-12 17:30:36260}
261
Eric Ortha97f0f72020-10-16 16:10:32262DnsResponse BuildTestDnsTextResponse(
Eric Orth828bd3ae2018-12-12 17:30:36263 std::string name,
264 std::vector<std::vector<std::string>> text_records,
265 std::string answer_name) {
266 if (answer_name.empty())
267 answer_name = name;
268
269 std::vector<DnsResourceRecord> answers;
Eric Ortha625b042019-01-16 01:14:45270 for (std::vector<std::string>& text_record : text_records) {
Eric Orth3b26e3ba2020-11-12 22:43:13271 answers.push_back(BuildTestTextRecord(answer_name, std::move(text_record)));
Eric Orth828bd3ae2018-12-12 17:30:36272 }
273
Eric Orth8539e492020-10-19 20:09:55274 return BuildTestDnsResponse(std::move(name), dns_protocol::kTypeTXT, answers);
Eric Orth828bd3ae2018-12-12 17:30:36275}
276
Eric Ortha97f0f72020-10-16 16:10:32277DnsResponse BuildTestDnsPointerResponse(std::string name,
278 std::vector<std::string> pointer_names,
279 std::string answer_name) {
Eric Orthe9db8d232019-01-14 21:24:45280 if (answer_name.empty())
281 answer_name = name;
282
283 std::vector<DnsResourceRecord> answers;
Eric Ortha625b042019-01-16 01:14:45284 for (std::string& pointer_name : pointer_names) {
Eric Orth8539e492020-10-19 20:09:55285 std::string rdata;
286 CHECK(DNSDomainFromDot(pointer_name, &rdata));
287
288 answers.push_back(BuildTestDnsRecord(answer_name, dns_protocol::kTypePTR,
289 std::move(rdata)));
Eric Orthe9db8d232019-01-14 21:24:45290 }
291
Eric Orth8539e492020-10-19 20:09:55292 return BuildTestDnsResponse(std::move(name), dns_protocol::kTypePTR, answers);
Eric Orthe9db8d232019-01-14 21:24:45293}
294
Eric Ortha97f0f72020-10-16 16:10:32295DnsResponse BuildTestDnsServiceResponse(
Eric Ortha625b042019-01-16 01:14:45296 std::string name,
297 std::vector<TestServiceRecord> service_records,
298 std::string answer_name) {
299 if (answer_name.empty())
300 answer_name = name;
301
302 std::vector<DnsResourceRecord> answers;
303 for (TestServiceRecord& service_record : service_records) {
Eric Orth8539e492020-10-19 20:09:55304 std::string rdata;
305 char num_buffer[2];
306 base::WriteBigEndian(num_buffer, service_record.priority);
307 rdata.append(num_buffer, 2);
308 base::WriteBigEndian(num_buffer, service_record.weight);
309 rdata.append(num_buffer, 2);
310 base::WriteBigEndian(num_buffer, service_record.port);
311 rdata.append(num_buffer, 2);
312 std::string dns_name;
313 CHECK(DNSDomainFromDot(service_record.target, &dns_name));
314 rdata += dns_name;
315
316 answers.push_back(BuildTestDnsRecord(answer_name, dns_protocol::kTypeSRV,
Peter Kastinge5a38ed2021-10-02 03:06:35317 std::move(rdata), base::Hours(5)));
Eric Ortha625b042019-01-16 01:14:45318 }
319
Eric Orth8539e492020-10-19 20:09:55320 return BuildTestDnsResponse(std::move(name), dns_protocol::kTypeSRV, answers);
Daniel McArdle2daa3ec2020-06-03 16:05:48321}
322
Eric Orth89726dd2020-10-13 20:19:53323MockDnsClientRule::Result::Result(ResultType type,
Eric Orthac9aafb2021-07-29 23:03:43324 absl::optional<DnsResponse> response,
325 absl::optional<int> net_error)
326 : type(type), response(std::move(response)), net_error(net_error) {}
Eric Orth828bd3ae2018-12-12 17:30:36327
Eric Ortha97f0f72020-10-16 16:10:32328MockDnsClientRule::Result::Result(DnsResponse response)
Peter Kastingd039b772021-08-18 00:06:20329 : type(ResultType::kOk),
330 response(std::move(response)),
331 net_error(absl::nullopt) {}
Eric Orth828bd3ae2018-12-12 17:30:36332
Peter Kastingd039b772021-08-18 00:06:20333MockDnsClientRule::Result::Result(Result&&) = default;
334
335MockDnsClientRule::Result& MockDnsClientRule::Result::operator=(Result&&) =
336 default;
Eric Orth828bd3ae2018-12-12 17:30:36337
338MockDnsClientRule::Result::~Result() = default;
339
Eric Orth502d5682019-04-12 00:21:33340MockDnsClientRule::MockDnsClientRule(const std::string& prefix,
341 uint16_t qtype,
dalyk4f4ac712019-05-31 16:33:13342 bool secure,
Eric Orth502d5682019-04-12 00:21:33343 Result result,
344 bool delay,
345 URLRequestContext* context)
346 : result(std::move(result)),
347 prefix(prefix),
348 qtype(qtype),
dalyk4f4ac712019-05-31 16:33:13349 secure(secure),
Eric Orth502d5682019-04-12 00:21:33350 delay(delay),
351 context(context) {}
352
353MockDnsClientRule::MockDnsClientRule(MockDnsClientRule&& rule) = default;
354
Eric Orth3421db382019-10-20 02:35:52355// A DnsTransaction which uses MockDnsClientRuleList to determine the response.
356class MockDnsTransactionFactory::MockTransaction
357 : public DnsTransaction,
358 public base::SupportsWeakPtr<MockTransaction> {
[email protected]78eac2a2012-03-14 19:09:27359 public:
Eric Orth3421db382019-10-20 02:35:52360 MockTransaction(const MockDnsClientRuleList& rules,
Eric Orthc4cca5d2021-07-02 19:59:01361 std::string hostname,
Eric Orth3421db382019-10-20 02:35:52362 uint16_t qtype,
363 bool secure,
Eric Orth7dc18e92020-02-13 20:27:56364 bool force_doh_server_available,
Eric Ortha093b092020-09-24 23:13:02365 SecureDnsMode secure_dns_mode,
Eric Orth7dc18e92020-02-13 20:27:56366 ResolveContext* resolve_context,
Eric Orth89726dd2020-10-13 20:19:53367 bool fast_timeout,
Eric Orth3421db382019-10-20 02:35:52368 DnsTransactionFactory::CallbackType callback)
Peter Kastingd039b772021-08-18 00:06:20369 : result_(MockDnsClientRule::ResultType::kFail),
Eric Orthc4cca5d2021-07-02 19:59:01370 hostname_(std::move(hostname)),
Eric Orth3421db382019-10-20 02:35:52371 qtype_(qtype),
372 callback_(std::move(callback)),
373 started_(false),
374 delayed_(false) {
Eric Orth7dc18e92020-02-13 20:27:56375 // Do not allow matching any rules if transaction is secure and no DoH
376 // servers are available.
377 if (!secure || force_doh_server_available ||
378 resolve_context->NumAvailableDohServers(
379 resolve_context->current_session_for_testing()) > 0) {
380 // Find the relevant rule which matches |qtype|, |secure|, prefix of
Eric Orthc4cca5d2021-07-02 19:59:01381 // |hostname_|, and |url_request_context| (iff the rule context is not
Eric Orth7dc18e92020-02-13 20:27:56382 // null).
383 for (size_t i = 0; i < rules.size(); ++i) {
384 const std::string& prefix = rules[i].prefix;
385 if ((rules[i].qtype == qtype) && (rules[i].secure == secure) &&
Eric Orthc4cca5d2021-07-02 19:59:01386 (hostname_.size() >= prefix.size()) &&
387 (hostname_.compare(0, prefix.size(), prefix) == 0) &&
Eric Orth7dc18e92020-02-13 20:27:56388 (!rules[i].context ||
389 rules[i].context == resolve_context->url_request_context())) {
390 const MockDnsClientRule::Result* result = &rules[i].result;
391 result_ = MockDnsClientRule::Result(result->type);
Eric Orthac9aafb2021-07-29 23:03:43392 result_.net_error = result->net_error;
Eric Orth7dc18e92020-02-13 20:27:56393 delayed_ = rules[i].delay;
[email protected]daae1322013-09-05 18:26:50394
Eric Orth7dc18e92020-02-13 20:27:56395 // Generate a DnsResponse when not provided with the rule.
396 std::vector<DnsResourceRecord> authority_records;
397 std::string dns_name;
398 CHECK(DNSDomainFromDot(hostname_, &dns_name));
Anton Bikineev068d2912021-05-15 20:43:52399 absl::optional<DnsQuery> query(absl::in_place, 22 /* id */, dns_name,
Eric Orth7dc18e92020-02-13 20:27:56400 qtype_);
401 switch (result->type) {
Peter Kastingd039b772021-08-18 00:06:20402 case MockDnsClientRule::ResultType::kNoDomain:
403 case MockDnsClientRule::ResultType::kEmpty:
Eric Orth7dc18e92020-02-13 20:27:56404 DCHECK(!result->response); // Not expected to be provided.
Eric Orth8539e492020-10-19 20:09:55405 authority_records = {BuildTestDnsRecord(
406 hostname_, dns_protocol::kTypeSOA, "fake rdata")};
Eric Ortha97f0f72020-10-16 16:10:32407 result_.response = DnsResponse(
Eric Orth7dc18e92020-02-13 20:27:56408 22 /* id */, false /* is_authoritative */,
409 std::vector<DnsResourceRecord>() /* answers */,
410 authority_records,
411 std::vector<DnsResourceRecord>() /* additional_records */,
412 query,
Peter Kastingd039b772021-08-18 00:06:20413 result->type == MockDnsClientRule::ResultType::kNoDomain
Eric Orth7dc18e92020-02-13 20:27:56414 ? dns_protocol::kRcodeNXDOMAIN
415 : 0);
416 break;
Peter Kastingd039b772021-08-18 00:06:20417 case MockDnsClientRule::ResultType::kFail:
Eric Orthac9aafb2021-07-29 23:03:43418 if (result->response)
419 SetResponse(result);
420 break;
Peter Kastingd039b772021-08-18 00:06:20421 case MockDnsClientRule::ResultType::kTimeout:
Eric Orth7dc18e92020-02-13 20:27:56422 DCHECK(!result->response); // Not expected to be provided.
423 break;
Peter Kastingd039b772021-08-18 00:06:20424 case MockDnsClientRule::ResultType::kSlow:
Eric Orth89726dd2020-10-13 20:19:53425 if (!fast_timeout)
426 SetResponse(result);
427 break;
Peter Kastingd039b772021-08-18 00:06:20428 case MockDnsClientRule::ResultType::kOk:
Eric Orth89726dd2020-10-13 20:19:53429 SetResponse(result);
Eric Orth7dc18e92020-02-13 20:27:56430 break;
Peter Kastingd039b772021-08-18 00:06:20431 case MockDnsClientRule::ResultType::kMalformed:
Eric Orth7dc18e92020-02-13 20:27:56432 DCHECK(!result->response); // Not expected to be provided.
433 result_.response = CreateMalformedResponse(hostname_, qtype_);
434 break;
Peter Kastingd039b772021-08-18 00:06:20435 case MockDnsClientRule::ResultType::kUnexpected:
Eric Orthcf8e00f2021-07-24 00:41:24436 ADD_FAILURE()
437 << "Unexpected DNS transaction created for hostname "
438 << hostname_;
439 break;
Eric Orth7dc18e92020-02-13 20:27:56440 }
Eric Orth2a61be82020-02-12 17:56:48441
Eric Orth7dc18e92020-02-13 20:27:56442 break;
443 }
Eric Orth3421db382019-10-20 02:35:52444 }
[email protected]daae1322013-09-05 18:26:50445 }
[email protected]0adcb2b2012-08-15 21:30:46446 }
447
Eric Orth3421db382019-10-20 02:35:52448 const std::string& GetHostname() const override { return hostname_; }
[email protected]daae1322013-09-05 18:26:50449
Eric Orth3421db382019-10-20 02:35:52450 uint16_t GetType() const override { return qtype_; }
451
452 void Start() override {
453 EXPECT_FALSE(started_);
454 started_ = true;
455 if (delayed_)
456 return;
457 // Using WeakPtr to cleanly cancel when transaction is destroyed.
458 base::ThreadTaskRunnerHandle::Get()->PostTask(
459 FROM_HERE, base::BindOnce(&MockTransaction::Finish, AsWeakPtr()));
460 }
461
462 void FinishDelayedTransaction() {
463 EXPECT_TRUE(delayed_);
464 delayed_ = false;
465 Finish();
466 }
467
468 bool delayed() const { return delayed_; }
469
470 private:
Eric Orth89726dd2020-10-13 20:19:53471 void SetResponse(const MockDnsClientRule::Result* result) {
472 if (result->response) {
473 // Copy response in case |result| is destroyed before the transaction
474 // completes.
Eric Ortha97f0f72020-10-16 16:10:32475 auto buffer_copy =
476 base::MakeRefCounted<IOBuffer>(result->response->io_buffer_size());
477 memcpy(buffer_copy->data(), result->response->io_buffer()->data(),
478 result->response->io_buffer_size());
479 result_.response = DnsResponse(std::move(buffer_copy),
480 result->response->io_buffer_size());
Eric Orth89726dd2020-10-13 20:19:53481 CHECK(result_.response->InitParseWithoutQuery(
482 result->response->io_buffer_size()));
483 } else {
484 // Generated response only available for address types.
485 DCHECK(qtype_ == dns_protocol::kTypeA ||
486 qtype_ == dns_protocol::kTypeAAAA);
Eric Ortha97f0f72020-10-16 16:10:32487 result_.response = BuildTestDnsAddressResponse(
488 hostname_, qtype_ == dns_protocol::kTypeA
489 ? IPAddress::IPv4Localhost()
490 : IPAddress::IPv6Localhost());
Eric Orth89726dd2020-10-13 20:19:53491 }
492 }
493
Eric Orth3421db382019-10-20 02:35:52494 void Finish() {
495 switch (result_.type) {
Peter Kastingd039b772021-08-18 00:06:20496 case MockDnsClientRule::ResultType::kNoDomain:
497 case MockDnsClientRule::ResultType::kFail: {
Eric Orthac9aafb2021-07-29 23:03:43498 int error = result_.net_error.value_or(ERR_NAME_NOT_RESOLVED);
499 DCHECK_NE(error, OK);
500 std::move(callback_).Run(this, error,
501 base::OptionalOrNullptr(result_.response),
502 absl::nullopt);
Eric Orth3421db382019-10-20 02:35:52503 break;
Eric Orthac9aafb2021-07-29 23:03:43504 }
Peter Kastingd039b772021-08-18 00:06:20505 case MockDnsClientRule::ResultType::kEmpty:
506 case MockDnsClientRule::ResultType::kOk:
507 case MockDnsClientRule::ResultType::kMalformed:
Eric Orthac9aafb2021-07-29 23:03:43508 DCHECK(!result_.net_error.has_value());
Eric Ortha97f0f72020-10-16 16:10:32509 std::move(callback_).Run(
Eric Orthac9aafb2021-07-29 23:03:43510 this, OK, base::OptionalOrNullptr(result_.response), absl::nullopt);
Eric Orth3421db382019-10-20 02:35:52511 break;
Peter Kastingd039b772021-08-18 00:06:20512 case MockDnsClientRule::ResultType::kTimeout:
Eric Orthac9aafb2021-07-29 23:03:43513 DCHECK(!result_.net_error.has_value());
Daniel McArdle4e2037e2020-06-11 22:40:51514 std::move(callback_).Run(this, ERR_DNS_TIMED_OUT, nullptr,
Anton Bikineev068d2912021-05-15 20:43:52515 absl::nullopt);
Eric Orth3421db382019-10-20 02:35:52516 break;
Peter Kastingd039b772021-08-18 00:06:20517 case MockDnsClientRule::ResultType::kSlow:
Eric Orth89726dd2020-10-13 20:19:53518 if (result_.response) {
Eric Ortha97f0f72020-10-16 16:10:32519 std::move(callback_).Run(
Eric Orthac9aafb2021-07-29 23:03:43520 this, result_.net_error.value_or(OK),
521 result_.response ? &result_.response.value() : nullptr,
Anton Bikineev068d2912021-05-15 20:43:52522 absl::nullopt);
Eric Orth89726dd2020-10-13 20:19:53523 } else {
Eric Orthac9aafb2021-07-29 23:03:43524 DCHECK(!result_.net_error.has_value());
Eric Orth89726dd2020-10-13 20:19:53525 std::move(callback_).Run(this, ERR_DNS_TIMED_OUT, nullptr,
Anton Bikineev068d2912021-05-15 20:43:52526 absl::nullopt);
Eric Orth89726dd2020-10-13 20:19:53527 }
Eric Orthcf8e00f2021-07-24 00:41:24528 break;
Peter Kastingd039b772021-08-18 00:06:20529 case MockDnsClientRule::ResultType::kUnexpected:
Eric Orthcf8e00f2021-07-24 00:41:24530 ADD_FAILURE() << "Unexpected DNS transaction completed for hostname "
531 << hostname_;
532 break;
Eric Orth3421db382019-10-20 02:35:52533 }
534 }
535
536 void SetRequestPriority(RequestPriority priority) override {}
537
538 MockDnsClientRule::Result result_;
539 const std::string hostname_;
540 const uint16_t qtype_;
541 DnsTransactionFactory::CallbackType callback_;
542 bool started_;
543 bool delayed_;
[email protected]0adcb2b2012-08-15 21:30:46544};
545
Eric Orth41b249e02020-01-03 20:21:47546class MockDnsTransactionFactory::MockDohProbeRunner : public DnsProbeRunner {
547 public:
548 explicit MockDohProbeRunner(base::WeakPtr<MockDnsTransactionFactory> factory)
549 : factory_(std::move(factory)) {}
550
551 ~MockDohProbeRunner() override {
552 if (factory_)
553 factory_->running_doh_probe_runners_.erase(this);
554 }
555
Eric Orth020e5fe2020-03-12 17:43:43556 void Start(bool network_change) override {
Eric Orth41b249e02020-01-03 20:21:47557 DCHECK(factory_);
558 factory_->running_doh_probe_runners_.insert(this);
559 }
560
Eric Orth41b249e02020-01-03 20:21:47561 base::TimeDelta GetDelayUntilNextProbeForTest(
562 size_t doh_server_index) const override {
563 NOTREACHED();
564 return base::TimeDelta();
565 }
566
567 private:
568 base::WeakPtr<MockDnsTransactionFactory> factory_;
569};
570
Eric Orth3421db382019-10-20 02:35:52571MockDnsTransactionFactory::MockDnsTransactionFactory(
572 MockDnsClientRuleList rules)
573 : rules_(std::move(rules)) {}
574
575MockDnsTransactionFactory::~MockDnsTransactionFactory() = default;
576
577std::unique_ptr<DnsTransaction> MockDnsTransactionFactory::CreateTransaction(
Eric Orthc4cca5d2021-07-02 19:59:01578 std::string hostname,
Eric Orth3421db382019-10-20 02:35:52579 uint16_t qtype,
580 DnsTransactionFactory::CallbackType callback,
581 const NetLogWithSource&,
582 bool secure,
Eric Ortha093b092020-09-24 23:13:02583 SecureDnsMode secure_dns_mode,
Eric Orth89726dd2020-10-13 20:19:53584 ResolveContext* resolve_context,
585 bool fast_timeout) {
Eric Orth3421db382019-10-20 02:35:52586 std::unique_ptr<MockTransaction> transaction =
Eric Orthc4cca5d2021-07-02 19:59:01587 std::make_unique<MockTransaction>(rules_, std::move(hostname), qtype,
588 secure, force_doh_server_available_,
589 secure_dns_mode, resolve_context,
590 fast_timeout, std::move(callback));
Eric Orth3421db382019-10-20 02:35:52591 if (transaction->delayed())
592 delayed_transactions_.push_back(transaction->AsWeakPtr());
593 return transaction;
594}
595
Eric Orth41b249e02020-01-03 20:21:47596std::unique_ptr<DnsProbeRunner> MockDnsTransactionFactory::CreateDohProbeRunner(
Eric Orth069a3c6e2020-01-31 23:14:24597 ResolveContext* resolve_context) {
Eric Orth41b249e02020-01-03 20:21:47598 return std::make_unique<MockDohProbeRunner>(weak_ptr_factory_.GetWeakPtr());
599}
600
Eric Orth3421db382019-10-20 02:35:52601void MockDnsTransactionFactory::AddEDNSOption(const OptRecordRdata::Opt& opt) {}
602
Eric Ortha093b092020-09-24 23:13:02603SecureDnsMode MockDnsTransactionFactory::GetSecureDnsModeForTest() {
604 return SecureDnsMode::kAutomatic;
Eric Orth3421db382019-10-20 02:35:52605}
606
607void MockDnsTransactionFactory::CompleteDelayedTransactions() {
608 DelayedTransactionList old_delayed_transactions;
609 old_delayed_transactions.swap(delayed_transactions_);
610 for (auto it = old_delayed_transactions.begin();
611 it != old_delayed_transactions.end(); ++it) {
612 if (it->get())
613 (*it)->FinishDelayedTransaction();
614 }
615}
616
David Van Cleve1fb5e8c2019-11-04 16:45:16617bool MockDnsTransactionFactory::CompleteOneDelayedTransactionOfType(
618 DnsQueryType type) {
619 for (base::WeakPtr<MockTransaction>& t : delayed_transactions_) {
620 if (t && t->GetType() == DnsQueryTypeToQtype(type)) {
621 t->FinishDelayedTransaction();
622 t.reset();
623 return true;
624 }
625 }
626 return false;
627}
628
Eric Orth394db1732019-08-27 20:09:39629MockDnsClient::MockDnsClient(DnsConfig config, MockDnsClientRuleList rules)
630 : config_(std::move(config)),
Eric Orth3421db382019-10-20 02:35:52631 factory_(new MockDnsTransactionFactory(std::move(rules))),
Eric Orth394db1732019-08-27 20:09:39632 address_sorter_(new MockAddressSorter()) {
633 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50634 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39635}
[email protected]78eac2a2012-03-14 19:09:27636
Chris Watkins68b15032017-12-01 03:07:13637MockDnsClient::~MockDnsClient() = default;
[email protected]78eac2a2012-03-14 19:09:27638
Eric Orth394db1732019-08-27 20:09:39639bool MockDnsClient::CanUseSecureDnsTransactions() const {
640 const DnsConfig* config = GetEffectiveConfig();
641 return config && config->IsValid() && !config->dns_over_https_servers.empty();
[email protected]daae1322013-09-05 18:26:50642}
[email protected]78eac2a2012-03-14 19:09:27643
Eric Orth394db1732019-08-27 20:09:39644bool MockDnsClient::CanUseInsecureDnsTransactions() const {
645 const DnsConfig* config = GetEffectiveConfig();
646 return config && config->IsValid() && insecure_enabled_ &&
647 !config->dns_over_tls_active;
648}
649
Eric Orth09746312021-05-05 15:44:58650bool MockDnsClient::CanQueryAdditionalTypesViaInsecureDns() const {
651 DCHECK(CanUseInsecureDnsTransactions());
652 return additional_types_enabled_;
653}
654
655void MockDnsClient::SetInsecureEnabled(bool enabled,
656 bool additional_types_enabled) {
Eric Orth394db1732019-08-27 20:09:39657 insecure_enabled_ = enabled;
Eric Orth09746312021-05-05 15:44:58658 additional_types_enabled_ = additional_types_enabled;
Eric Orth394db1732019-08-27 20:09:39659}
660
Eric Orth069a3c6e2020-01-31 23:14:24661bool MockDnsClient::FallbackFromSecureTransactionPreferred(
662 ResolveContext* context) const {
Eric Orth7dc18e92020-02-13 20:27:56663 bool doh_server_available =
664 force_doh_server_available_ ||
665 context->NumAvailableDohServers(session_.get()) > 0;
666 return !CanUseSecureDnsTransactions() || !doh_server_available;
dalykc2adf182019-09-02 14:31:22667}
668
Eric Orth394db1732019-08-27 20:09:39669bool MockDnsClient::FallbackFromInsecureTransactionPreferred() const {
670 return !CanUseInsecureDnsTransactions() ||
671 fallback_failures_ >= max_fallback_failures_;
672}
673
Anton Bikineev068d2912021-05-15 20:43:52674bool MockDnsClient::SetSystemConfig(absl::optional<DnsConfig> system_config) {
Eric Orth394db1732019-08-27 20:09:39675 if (ignore_system_config_changes_)
676 return false;
677
Anton Bikineev068d2912021-05-15 20:43:52678 absl::optional<DnsConfig> before = effective_config_;
Eric Orth394db1732019-08-27 20:09:39679 config_ = std::move(system_config);
680 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50681 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39682 return before != effective_config_;
683}
684
685bool MockDnsClient::SetConfigOverrides(DnsConfigOverrides config_overrides) {
Anton Bikineev068d2912021-05-15 20:43:52686 absl::optional<DnsConfig> before = effective_config_;
Eric Orth394db1732019-08-27 20:09:39687 overrides_ = std::move(config_overrides);
688 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50689 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39690 return before != effective_config_;
691}
692
Eric Orth020e5fe2020-03-12 17:43:43693void MockDnsClient::ReplaceCurrentSession() {
694 // Noop if no current effective config.
695 session_ = BuildSession();
696}
697
Eric Orthaf82b49a2020-02-01 01:48:50698DnsSession* MockDnsClient::GetCurrentSession() {
699 return session_.get();
700}
701
Eric Orth394db1732019-08-27 20:09:39702const DnsConfig* MockDnsClient::GetEffectiveConfig() const {
703 return effective_config_.has_value() ? &effective_config_.value() : nullptr;
704}
705
706const DnsHosts* MockDnsClient::GetHosts() const {
707 const DnsConfig* config = GetEffectiveConfig();
708 if (!config)
709 return nullptr;
710
711 return &config->hosts;
[email protected]daae1322013-09-05 18:26:50712}
[email protected]78eac2a2012-03-14 19:09:27713
[email protected]daae1322013-09-05 18:26:50714DnsTransactionFactory* MockDnsClient::GetTransactionFactory() {
Eric Orth394db1732019-08-27 20:09:39715 return GetEffectiveConfig() ? factory_.get() : nullptr;
[email protected]daae1322013-09-05 18:26:50716}
[email protected]78eac2a2012-03-14 19:09:27717
[email protected]daae1322013-09-05 18:26:50718AddressSorter* MockDnsClient::GetAddressSorter() {
Eric Orth394db1732019-08-27 20:09:39719 return GetEffectiveConfig() ? address_sorter_.get() : nullptr;
720}
721
722void MockDnsClient::IncrementInsecureFallbackFailures() {
723 ++fallback_failures_;
724}
725
726void MockDnsClient::ClearInsecureFallbackFailures() {
727 fallback_failures_ = 0;
728}
729
Anton Bikineev068d2912021-05-15 20:43:52730absl::optional<DnsConfig> MockDnsClient::GetSystemConfigForTesting() const {
Eric Orth394db1732019-08-27 20:09:39731 return config_;
732}
733
734DnsConfigOverrides MockDnsClient::GetConfigOverridesForTesting() const {
735 return overrides_;
[email protected]daae1322013-09-05 18:26:50736}
[email protected]0adcb2b2012-08-15 21:30:46737
Eric Orth3421db382019-10-20 02:35:52738void MockDnsClient::SetTransactionFactoryForTesting(
739 std::unique_ptr<DnsTransactionFactory> factory) {
740 NOTREACHED();
741}
742
Benjamin M. Schwartz6f719eb2021-12-15 17:47:28743absl::optional<AddressList> MockDnsClient::GetPresetAddrs(
744 const url::SchemeHostPort& endpoint) const {
745 EXPECT_THAT(preset_endpoint_, testing::Optional(endpoint));
746 return preset_addrs_;
747}
748
[email protected]daae1322013-09-05 18:26:50749void MockDnsClient::CompleteDelayedTransactions() {
750 factory_->CompleteDelayedTransactions();
[email protected]78eac2a2012-03-14 19:09:27751}
752
David Van Cleve1fb5e8c2019-11-04 16:45:16753bool MockDnsClient::CompleteOneDelayedTransactionOfType(DnsQueryType type) {
754 return factory_->CompleteOneDelayedTransactionOfType(type);
755}
756
Eric Orth7dc18e92020-02-13 20:27:56757void MockDnsClient::SetForceDohServerAvailable(bool available) {
758 force_doh_server_available_ = available;
759 factory_->set_force_doh_server_available(available);
760}
761
Anton Bikineev068d2912021-05-15 20:43:52762absl::optional<DnsConfig> MockDnsClient::BuildEffectiveConfig() {
Eric Orth394db1732019-08-27 20:09:39763 if (overrides_.OverridesEverything())
764 return overrides_.ApplyOverrides(DnsConfig());
765 if (!config_ || !config_.value().IsValid())
Anton Bikineev068d2912021-05-15 20:43:52766 return absl::nullopt;
Eric Orth394db1732019-08-27 20:09:39767
768 return overrides_.ApplyOverrides(config_.value());
769}
770
Eric Orthaf82b49a2020-02-01 01:48:50771scoped_refptr<DnsSession> MockDnsClient::BuildSession() {
772 if (!effective_config_)
773 return nullptr;
774
775 // Session not expected to be used for anything that will actually require
776 // random numbers.
777 auto null_random_callback =
778 base::BindRepeating([](int, int) -> int { IMMEDIATE_CRASH(); });
779
Eric Orth9300cc62020-08-21 00:29:34780 auto socket_allocator = std::make_unique<DnsSocketAllocator>(
Eric Orth990a74a92020-08-20 18:41:26781 &socket_factory_, effective_config_.value().nameservers,
782 nullptr /* net_log */);
783
Eric Orthaf82b49a2020-02-01 01:48:50784 return base::MakeRefCounted<DnsSession>(
Eric Orth9300cc62020-08-21 00:29:34785 effective_config_.value(), std::move(socket_allocator),
786 null_random_callback, nullptr /* net_log */);
Eric Orthaf82b49a2020-02-01 01:48:50787}
788
[email protected]78eac2a2012-03-14 19:09:27789} // namespace net