1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18 #define LOG_TAG "resolv_private_dns_test"
19
20 #include <regex>
21
22 #include <aidl/android/net/IDnsResolver.h>
23 #include <android-base/file.h>
24 #include <android-base/logging.h>
25 #include <android/binder_manager.h>
26 #include <android/binder_process.h>
27 #include <gmock/gmock.h>
28 #include <gtest/gtest.h>
29 #include <netdutils/InternetAddresses.h>
30 #include <netdutils/NetNativeTestBase.h>
31 #include <netdutils/Stopwatch.h>
32 #include <nettestutils/DumpService.h>
33
34 #include "doh_frontend.h"
35 #include "tests/dns_responder/dns_responder.h"
36 #include "tests/dns_responder/dns_responder_client_ndk.h"
37 #include "tests/dns_responder/dns_tls_frontend.h"
38 #include "tests/resolv_test_utils.h"
39 #include "tests/unsolicited_listener/unsolicited_event_listener.h"
40
41 #include <android/multinetwork.h> // ResNsendFlags
42 #include <arpa/inet.h>
43 #include <poll.h>
44 #include "NetdClient.h"
45
46 using aidl::android::net::resolv::aidl::DohParamsParcel;
47 using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener;
48 using android::base::GetProperty;
49 using android::base::ReadFdToString;
50 using android::base::unique_fd;
51 using android::net::resolv::aidl::UnsolicitedEventListener;
52 using android::netdutils::IPSockAddr;
53 using android::netdutils::ScopedAddrinfo;
54 using android::netdutils::Stopwatch;
55 using std::chrono::milliseconds;
56 using std::this_thread::sleep_for;
57 using ::testing::AnyOf;
58
59 constexpr int MAXPACKET = (8 * 1024);
60
61 // Constant values sync'd from PrivateDnsConfiguration.
62 constexpr int kDohIdleDefaultTimeoutMs = 55000;
63
64 namespace {
65
getAsyncResponse(int fd,int * rcode,uint8_t * buf,int bufLen)66 int getAsyncResponse(int fd, int* rcode, uint8_t* buf, int bufLen) {
67 struct pollfd wait_fd[1];
68 wait_fd[0].fd = fd;
69 wait_fd[0].events = POLLIN;
70 short revents;
71
72 if (int ret = poll(wait_fd, 1, -1); ret <= 0) {
73 return -1;
74 }
75
76 revents = wait_fd[0].revents;
77 if (revents & POLLIN) {
78 return resNetworkResult(fd, rcode, buf, bufLen);
79 }
80 return -1;
81 }
82
toString(uint8_t * buf,int bufLen,int ipType)83 std::string toString(uint8_t* buf, int bufLen, int ipType) {
84 ns_msg handle;
85 ns_rr rr;
86
87 if (ns_initparse((const uint8_t*)buf, bufLen, &handle) >= 0) {
88 if (ns_parserr(&handle, ns_s_an, 0, &rr) == 0) {
89 const uint8_t* rdata = ns_rr_rdata(rr);
90 char buffer[INET6_ADDRSTRLEN];
91 if (inet_ntop(ipType, (const char*)rdata, buffer, sizeof(buffer))) {
92 return buffer;
93 }
94 }
95 }
96 return "";
97 }
98
expectAnswersValid(int fd,int ipType,const std::string & expectedAnswer)99 void expectAnswersValid(int fd, int ipType, const std::string& expectedAnswer) {
100 int rcode = -1;
101 uint8_t buf[MAXPACKET] = {};
102
103 int res = getAsyncResponse(fd, &rcode, buf, MAXPACKET);
104 EXPECT_GT(res, 0);
105 EXPECT_EQ(expectedAnswer, toString(buf, res, ipType));
106 }
107
108 // A helper which can propagate the failure to outside of the stmt to know which line
109 // of stmt fails. The expectation fails only for the first failed stmt.
110 #define EXPECT_NO_FAILURE(stmt) \
111 do { \
112 bool alreadyFailed = HasFailure(); \
113 stmt; \
114 if (!alreadyFailed && HasFailure()) EXPECT_FALSE(HasFailure()); \
115 } while (0)
116
117 } // namespace
118
119 // Base class to deal with netd binder service and resolver binder service.
120 // TODO: derive ResolverTest from this base class.
121 class BaseTest : public NetNativeTestBase {
122 public:
SetUpTestSuite()123 static void SetUpTestSuite() {
124 // Get binder service.
125 // Note that |mDnsClient| is not used for getting binder service in this static function.
126 // The reason is that wants to keep |mDnsClient| as a non-static data member. |mDnsClient|
127 // which sets up device network configuration could be independent from every test.
128 // TODO: Perhaps add a static function in resolv_test_binder_utils.{cpp,h} to get binder
129 // service.
130 AIBinder* binder = AServiceManager_getService("dnsresolver");
131 sResolvBinder = ndk::SpAIBinder(binder);
132 auto resolvService = aidl::android::net::IDnsResolver::fromBinder(sResolvBinder);
133 ASSERT_NE(nullptr, resolvService.get());
134
135 // Subscribe the death recipient to the service IDnsResolver for detecting Netd death.
136 // GTEST assertion macros are not invoked for generating a test failure in the death
137 // recipient because the macros can't indicate failed test if Netd died between tests.
138 // Moreover, continuing testing may have no meaningful after Netd death. Therefore, the
139 // death recipient aborts process by GTEST_LOG_(FATAL) once Netd died.
140 sResolvDeathRecipient = AIBinder_DeathRecipient_new([](void*) {
141 constexpr char errorMessage[] = "Netd died";
142 LOG(ERROR) << errorMessage;
143 GTEST_LOG_(FATAL) << errorMessage;
144 });
145 ASSERT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, sResolvDeathRecipient, nullptr));
146
147 // Subscribe the unsolicited event listener for verifying unsolicited event contents.
148 sUnsolicitedEventListener = ndk::SharedRefBase::make<UnsolicitedEventListener>(TEST_NETID);
149 ASSERT_TRUE(
150 resolvService->registerUnsolicitedEventListener(sUnsolicitedEventListener).isOk());
151
152 // Start the binder thread pool for listening DNS metrics events and receiving death
153 // recipient.
154 ABinderProcess_startThreadPool();
155 }
TearDownTestSuite()156 static void TearDownTestSuite() { AIBinder_DeathRecipient_delete(sResolvDeathRecipient); }
157
158 protected:
SetUp()159 void SetUp() {
160 mDnsClient.SetUp();
161 sUnsolicitedEventListener->reset();
162 }
163
TearDown()164 void TearDown() {
165 // Ensure the dump works at the end of each test.
166 mDnsClient.TearDown();
167 }
168
resetNetwork()169 void resetNetwork() {
170 EXPECT_EQ(mDnsClient.TearDownOemNetwork(TEST_NETID), 0);
171 EXPECT_EQ(mDnsClient.SetupOemNetwork(TEST_NETID), 0);
172 }
173
flushCache()174 void flushCache() { mDnsClient.resolvService()->flushNetworkCache(TEST_NETID); }
175
WaitForDotValidation(std::string serverAddr,bool validated)176 bool WaitForDotValidation(std::string serverAddr, bool validated) {
177 return WaitForPrivateDnsValidation(serverAddr, validated,
178 IDnsResolverUnsolicitedEventListener::PROTOCOL_DOT);
179 }
180
WaitForDotValidationSuccess(std::string serverAddr)181 bool WaitForDotValidationSuccess(std::string serverAddr) {
182 return WaitForDotValidation(serverAddr, true);
183 }
184
WaitForDotValidationFailure(std::string serverAddr)185 bool WaitForDotValidationFailure(std::string serverAddr) {
186 return WaitForDotValidation(serverAddr, false);
187 }
188
WaitForDohValidation(std::string serverAddr,bool validated)189 bool WaitForDohValidation(std::string serverAddr, bool validated) {
190 return WaitForPrivateDnsValidation(serverAddr, validated,
191 IDnsResolverUnsolicitedEventListener::PROTOCOL_DOH);
192 }
193
WaitForDohValidationSuccess(std::string serverAddr)194 bool WaitForDohValidationSuccess(std::string serverAddr) {
195 return WaitForDohValidation(serverAddr, true);
196 }
197
WaitForDohValidationFailure(std::string serverAddr)198 bool WaitForDohValidationFailure(std::string serverAddr) {
199 return WaitForDohValidation(serverAddr, false);
200 }
201
WaitForPrivateDnsValidation(std::string serverAddr,bool validated,int protocol)202 bool WaitForPrivateDnsValidation(std::string serverAddr, bool validated, int protocol) {
203 return sUnsolicitedEventListener->waitForPrivateDnsValidation(
204 serverAddr,
205 validated ? IDnsResolverUnsolicitedEventListener::VALIDATION_RESULT_SUCCESS
206 : IDnsResolverUnsolicitedEventListener::VALIDATION_RESULT_FAILURE,
207 protocol);
208 }
209
hasUncaughtPrivateDnsValidation(const std::string & serverAddr)210 bool hasUncaughtPrivateDnsValidation(const std::string& serverAddr) {
211 sleep_for(milliseconds(200));
212 return sUnsolicitedEventListener->findValidationRecord(
213 serverAddr, IDnsResolverUnsolicitedEventListener::PROTOCOL_DOT) ||
214 sUnsolicitedEventListener->findValidationRecord(
215 serverAddr, IDnsResolverUnsolicitedEventListener::PROTOCOL_DOH);
216 }
217
expectLog(const std::string & ipAddrOrNoData,const std::string & port)218 bool expectLog(const std::string& ipAddrOrNoData, const std::string& port) {
219 std::vector<std::string> lines;
220 const android::status_t ret =
221 dumpService(sResolvBinder, /*args=*/nullptr, /*num_args=*/0, lines);
222 if (ret != android::OK) {
223 ADD_FAILURE() << "Error dumping service: " << android::statusToString(ret);
224 return false;
225 }
226
227 const std::string expectedLog =
228 port.empty() ? ipAddrOrNoData
229 : IPSockAddr::toIPSockAddr(ipAddrOrNoData, std::stoi(port)).toString();
230 const std::regex pattern(R"(^\s{4,}([0-9a-fA-F:\.\]\[]*)[ ]?([<(].*[>)])[ ]?(\S*)$)");
231
232 for (const auto& line : lines) {
233 if (line.empty()) continue;
234
235 std::smatch match;
236 if (std::regex_match(line, match, pattern)) {
237 if (match[1] == expectedLog || match[2] == expectedLog) return true;
238 }
239 }
240 return false;
241 }
242
243 DnsResponderClient mDnsClient;
244
245 // Use a shared static DNS listener for all tests to avoid registering lots of listeners
246 // which may be released late until process terminated. Currently, registered DNS listener
247 // is removed by binder death notification which is fired when the process hosting an
248 // IBinder has gone away. If every test registers its DNS listener, Netd
249 // may temporarily hold lots of dead listeners until the unit test process terminates.
250 // TODO: Perhaps add an unregistering listener binder call or fork a listener process which
251 // could be terminated earlier.
252 inline static std::shared_ptr<UnsolicitedEventListener> sUnsolicitedEventListener;
253
254 // Use a shared static death recipient to monitor the service death. The static death
255 // recipient could monitor the death not only during the test but also between tests.
256 inline static AIBinder_DeathRecipient* sResolvDeathRecipient;
257
258 // The linked AIBinder_DeathRecipient will be automatically unlinked if the binder is deleted.
259 // The binder needs to be retained throughout tests.
260 inline static ndk::SpAIBinder sResolvBinder;
261 };
262
263 class BasePrivateDnsTest : public BaseTest {
264 public:
SetUpTestSuite()265 static void SetUpTestSuite() {
266 BaseTest::SetUpTestSuite();
267 test::DohFrontend::initRustAndroidLogger();
268 }
269
270 protected:
SetUp()271 void SetUp() override {
272 mDohQueryTimeoutScopedProp =
273 std::make_unique<ScopedSystemProperties>(kDohQueryTimeoutFlag, "1000");
274 unsigned int expectedProbeTimeout = kExpectedDohValidationTimeWhenTimeout.count();
275 mDohProbeTimeoutScopedProp = std::make_unique<ScopedSystemProperties>(
276 kDohProbeTimeoutFlag, std::to_string(expectedProbeTimeout));
277 BaseTest::SetUp();
278
279 static const std::vector<DnsRecord> records = {
280 {kQueryHostname, ns_type::ns_t_a, kQueryAnswerA},
281 {kQueryHostname, ns_type::ns_t_aaaa, kQueryAnswerAAAA},
282 };
283
284 for (const auto& r : records) {
285 dns.addMapping(r.host_name, r.type, r.addr);
286 dot_backend.addMapping(r.host_name, r.type, r.addr);
287 doh_backend.addMapping(r.host_name, r.type, r.addr);
288 }
289 }
290
TearDown()291 void TearDown() override {
292 DumpResolverService();
293 BaseTest::TearDown();
294 }
295
sendQueryAndCheckResult(const char * host_name=kQueryHostname)296 void sendQueryAndCheckResult(const char* host_name = kQueryHostname) {
297 const addrinfo hints = {.ai_socktype = SOCK_DGRAM};
298 ScopedAddrinfo result = safe_getaddrinfo(host_name, nullptr, &hints);
299 EXPECT_THAT(ToStrings(result),
300 testing::UnorderedElementsAreArray({kQueryAnswerAAAA, kQueryAnswerA}));
301 };
302
expectQueries(int dnsQueries,int dotQueries,int dohQueries)303 void expectQueries(int dnsQueries, int dotQueries, int dohQueries) {
304 EXPECT_EQ(dns.queries().size(), static_cast<size_t>(dnsQueries));
305 EXPECT_EQ(dot.queries(), dotQueries);
306 EXPECT_EQ(doh.queries(), dohQueries);
307 }
308
309 // Used when a DoH probe is sent while the DoH server doesn't respond.
waitForDohValidationTimeout()310 void waitForDohValidationTimeout() {
311 std::this_thread::sleep_for(kExpectedDohValidationTimeWhenTimeout);
312 }
313
314 // Used when a DoH probe is sent while the DoH server is not listening on the port.
waitForDohValidationFailed()315 void waitForDohValidationFailed() {
316 std::this_thread::sleep_for(kExpectedDohValidationTimeWhenServerUnreachable);
317 }
318
DumpResolverService()319 void DumpResolverService() {
320 unique_fd fd(open("/dev/null", O_WRONLY));
321 EXPECT_EQ(mDnsClient.resolvService()->dump(fd, nullptr, 0), 0);
322
323 const char* querylogCmd[] = {"querylog"}; // Keep it sync with DnsQueryLog::DUMP_KEYWORD.
324 EXPECT_EQ(mDnsClient.resolvService()->dump(fd, querylogCmd, std::size(querylogCmd)), 0);
325 }
326
expectQueriesAreBlocked()327 void expectQueriesAreBlocked() {
328 // getaddrinfo should fail
329 const addrinfo hints = {.ai_socktype = SOCK_DGRAM};
330 EXPECT_FALSE(safe_getaddrinfo(kQueryHostname, nullptr, &hints));
331
332 // gethostbyname should fail
333 EXPECT_FALSE(gethostbyname(kQueryHostname));
334
335 // gethostbyaddr should fail
336 in6_addr v6addr;
337 inet_pton(AF_INET6, "2001:db8::102:304", &v6addr);
338 EXPECT_FALSE(gethostbyaddr(&v6addr, sizeof(v6addr), AF_INET6));
339
340 // resNetworkQuery should fail
341 int fd = resNetworkQuery(TEST_NETID, kQueryHostname, ns_c_in, ns_t_aaaa, 0);
342 EXPECT_TRUE(fd != -1);
343
344 uint8_t buf[MAXPACKET] = {};
345 int rcode;
346 EXPECT_EQ(-ECONNREFUSED, getAsyncResponse(fd, &rcode, buf, MAXPACKET));
347 }
348
349 static constexpr milliseconds kExpectedDohValidationTimeWhenTimeout{1000};
350 static constexpr milliseconds kExpectedDohValidationTimeWhenServerUnreachable{1000};
351 static constexpr char kQueryHostname[] = "TransportParameterizedTest.example.com.";
352 static constexpr char kQueryAnswerA[] = "1.2.3.4";
353 static constexpr char kQueryAnswerAAAA[] = "2001:db8::100";
354
355 test::DNSResponder dns{test::kDefaultListenAddr, kDnsPortString};
356 test::DohFrontend doh{test::kDefaultListenAddr, kDohPortString, "127.0.1.3", kDnsPortString};
357 test::DnsTlsFrontend dot{test::kDefaultListenAddr, kDotPortString, "127.0.2.3", kDnsPortString};
358 test::DNSResponder doh_backend{"127.0.1.3", kDnsPortString};
359 test::DNSResponder dot_backend{"127.0.2.3", kDnsPortString};
360
361 // Used to set up a shorter timeout.
362 std::unique_ptr<ScopedSystemProperties> mDohQueryTimeoutScopedProp;
363 std::unique_ptr<ScopedSystemProperties> mDohProbeTimeoutScopedProp;
364 };
365
366 // Parameterized test for the combination of DoH and DoT.
367 // - DoT: the assigned private DNS servers support DoT only.
368 // - DoH: the assigned private DNS servers support DoH only.
369 // - DOT + DoH: the assigned private DNS servers support both DoT and DoH.
370 class TransportParameterizedTest : public BasePrivateDnsTest,
371 public testing::WithParamInterface<uint8_t> {
372 public:
373 static constexpr uint8_t kDotBit = 0x01;
374 static constexpr uint8_t kDohBit = 0x02;
375 static constexpr std::array<uint8_t, 3> sParams = {kDotBit, kDohBit, kDotBit | kDohBit};
376
377 protected:
SetUp()378 void SetUp() override {
379 BasePrivateDnsTest::SetUp();
380
381 ASSERT_TRUE(dns.startServer());
382 if (testParamHasDot()) {
383 ASSERT_TRUE(dot_backend.startServer());
384 ASSERT_TRUE(dot.startServer());
385 }
386 if (testParamHasDoh()) {
387 ASSERT_TRUE(doh_backend.startServer());
388 ASSERT_TRUE(doh.startServer());
389 }
390 SetMdnsRoute();
391 }
392
TearDown()393 void TearDown() override {
394 RemoveMdnsRoute();
395 BasePrivateDnsTest::TearDown();
396 }
397
testParamHasDot()398 bool testParamHasDot() { return GetParam() & kDotBit; }
testParamHasDoh()399 bool testParamHasDoh() { return GetParam() & kDohBit; }
400 };
401
402 INSTANTIATE_TEST_SUITE_P(PrivateDns, TransportParameterizedTest,
403 testing::ValuesIn(TransportParameterizedTest::sParams),
__anon5805527c0302(const testing::TestParamInfo<uint8_t>& info) 404 [](const testing::TestParamInfo<uint8_t>& info) {
405 std::string name;
406 if (info.param & TransportParameterizedTest::kDotBit) name += "DoT";
407 if (info.param & TransportParameterizedTest::kDohBit) name += "DoH";
408 return name;
409 });
410
TEST_P(TransportParameterizedTest,GetAddrInfo)411 TEST_P(TransportParameterizedTest, GetAddrInfo) {
412 // TODO: Remove the flags and fix the test.
413 ScopedSystemProperties sp1(kDotAsyncHandshakeFlag, "0");
414 ScopedSystemProperties sp2(kDotMaxretriesFlag, "3");
415 resetNetwork();
416
417 const auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
418 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
419
420 if (testParamHasDoh()) EXPECT_TRUE(WaitForDohValidationSuccess(test::kDefaultListenAddr));
421 if (testParamHasDot()) EXPECT_TRUE(WaitForDotValidationSuccess(test::kDefaultListenAddr));
422
423 // This waiting time is expected to avoid that the DoH validation event interferes other tests.
424 if (!testParamHasDoh()) waitForDohValidationFailed();
425
426 // Have the test independent of the number of sent queries in private DNS validation, because
427 // the DnsResolver can send either 1 or 2 queries in DoT validation.
428 if (testParamHasDoh()) {
429 doh.clearQueries();
430 }
431 if (testParamHasDot()) {
432 EXPECT_TRUE(dot.waitForQueries(1));
433 dot.clearQueries();
434 }
435 dns.clearQueries();
436
437 EXPECT_NO_FAILURE(sendQueryAndCheckResult());
438 if (testParamHasDoh()) {
439 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 2 /* doh */));
440 } else {
441 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 2 /* dot */, 0 /* doh */));
442 }
443
444 // Stop the private DNS servers. Since we are in opportunistic mode, queries will
445 // fall back to the cleartext nameserver.
446 flushCache();
447 dot.stopServer();
448 doh.stopServer();
449
450 EXPECT_NO_FAILURE(sendQueryAndCheckResult());
451 if (testParamHasDoh()) {
452 EXPECT_NO_FAILURE(expectQueries(2 /* dns */, 0 /* dot */, 2 /* doh */));
453 } else {
454 EXPECT_NO_FAILURE(expectQueries(2 /* dns */, 2 /* dot */, 0 /* doh */));
455 }
456 }
457
TEST_P(TransportParameterizedTest,MdnsGetAddrInfo_fallback)458 TEST_P(TransportParameterizedTest, MdnsGetAddrInfo_fallback) {
459 // TODO: Remove the flags and fix the test.
460 ScopedSystemProperties sp1(kDotAsyncHandshakeFlag, "0");
461 ScopedSystemProperties sp2(kDotMaxretriesFlag, "3");
462 resetNetwork();
463
464 constexpr char host_name[] = "hello.local.";
465 test::DNSResponder mdnsv4("127.0.0.3", test::kDefaultMdnsListenService,
466 static_cast<ns_rcode>(-1));
467 test::DNSResponder mdnsv6("::1", test::kDefaultMdnsListenService, static_cast<ns_rcode>(-1));
468 // Set unresponsive on multicast.
469 mdnsv4.setResponseProbability(0.0);
470 mdnsv6.setResponseProbability(0.0);
471 ASSERT_TRUE(mdnsv4.startServer());
472 ASSERT_TRUE(mdnsv6.startServer());
473
474 const std::vector<DnsRecord> records = {
475 {host_name, ns_type::ns_t_a, kQueryAnswerA},
476 {host_name, ns_type::ns_t_aaaa, kQueryAnswerAAAA},
477 };
478
479 for (const auto& r : records) {
480 dns.addMapping(r.host_name, r.type, r.addr);
481 dot_backend.addMapping(r.host_name, r.type, r.addr);
482 doh_backend.addMapping(r.host_name, r.type, r.addr);
483 }
484
485 auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
486 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
487
488 if (testParamHasDoh()) EXPECT_TRUE(WaitForDohValidationSuccess(test::kDefaultListenAddr));
489 if (testParamHasDot()) EXPECT_TRUE(WaitForDotValidationSuccess(test::kDefaultListenAddr));
490
491 // This waiting time is expected to avoid that the DoH validation event interferes other tests.
492 if (!testParamHasDoh()) waitForDohValidationFailed();
493
494 // Have the test independent of the number of sent queries in private DNS validation, because
495 // the DnsResolver can send either 1 or 2 queries in DoT validation.
496 if (testParamHasDoh()) {
497 doh.clearQueries();
498 }
499 if (testParamHasDot()) {
500 EXPECT_TRUE(dot.waitForQueries(1));
501 dot.clearQueries();
502 }
503 dns.clearQueries();
504
505 EXPECT_NO_FAILURE(sendQueryAndCheckResult("hello.local"));
506 EXPECT_EQ(1U, GetNumQueries(mdnsv4, host_name));
507 EXPECT_EQ(1U, GetNumQueries(mdnsv6, host_name));
508 if (testParamHasDoh()) {
509 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 2 /* doh */));
510 } else {
511 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 2 /* dot */, 0 /* doh */));
512 }
513
514 // Stop the private DNS servers. Since we are in opportunistic mode, queries will
515 // fall back to the cleartext nameserver.
516 flushCache();
517 dot.stopServer();
518 doh.stopServer();
519 mdnsv4.clearQueries();
520 mdnsv6.clearQueries();
521
522 EXPECT_NO_FAILURE(sendQueryAndCheckResult("hello.local"));
523 EXPECT_EQ(1U, GetNumQueries(mdnsv4, host_name));
524 EXPECT_EQ(1U, GetNumQueries(mdnsv6, host_name));
525 if (testParamHasDoh()) {
526 EXPECT_NO_FAILURE(expectQueries(2 /* dns */, 0 /* dot */, 2 /* doh */));
527 } else {
528 EXPECT_NO_FAILURE(expectQueries(2 /* dns */, 2 /* dot */, 0 /* doh */));
529 }
530 }
531
TEST_P(TransportParameterizedTest,BlockDnsQuery)532 TEST_P(TransportParameterizedTest, BlockDnsQuery) {
533 SKIP_IF_BEFORE_T;
534 SKIP_IF_DEPENDENT_LIB_DOES_NOT_EXIST(DNS_HELPER);
535
536 constexpr char ptr_name[] = "v4v6.example.com.";
537 // PTR record for IPv6 address 2001:db8::102:304
538 constexpr char ptr_addr_v6[] =
539 "4.0.3.0.2.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.";
540 const DnsRecord r = {ptr_addr_v6, ns_type::ns_t_ptr, ptr_name};
541 dns.addMapping(r.host_name, r.type, r.addr);
542 dot_backend.addMapping(r.host_name, r.type, r.addr);
543 doh_backend.addMapping(r.host_name, r.type, r.addr);
544
545 // TODO: Remove the flags and fix the test.
546 // These two flags are not necessary for this test case because the test does not expect DNS
547 // queries to be sent by DNS resolver. However, We should still set these two flags so that we
548 // don't forget to set them when writing similar tests in the future by referring to this one.
549 ScopedSystemProperties sp1(kDotAsyncHandshakeFlag, "0");
550 ScopedSystemProperties sp2(kDotMaxretriesFlag, "3");
551
552 auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
553 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
554
555 if (testParamHasDoh()) EXPECT_TRUE(WaitForDohValidationSuccess(test::kDefaultListenAddr));
556 if (testParamHasDot()) EXPECT_TRUE(WaitForDotValidationSuccess(test::kDefaultListenAddr));
557
558 // This waiting time is expected to avoid that the DoH validation event interferes other tests.
559 if (!testParamHasDoh()) waitForDohValidationFailed();
560
561 // Have the test independent of the number of sent queries in private DNS validation, because
562 // the DnsResolver can send either 1 or 2 queries in DoT validation.
563 if (testParamHasDoh()) {
564 doh.clearQueries();
565 }
566 if (testParamHasDot()) {
567 EXPECT_TRUE(dot.waitForQueries(1));
568 dot.clearQueries();
569 }
570 dns.clearQueries();
571
572 for (const bool testDataSaver : {false, true}) {
573 SCOPED_TRACE(fmt::format("test {}", testDataSaver ? "data saver" : "UID firewall rules"));
574 if (testDataSaver) {
575 // Data Saver applies on metered networks only.
576 parcel.meteredNetwork = true;
577 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
578
579 // Block network access by enabling data saver.
580 ScopedSetDataSaverByBPF scopedSetDataSaverByBPF(true);
581 ScopedChangeUID scopedChangeUID(TEST_UID);
582
583 // DataSaver information is only meaningful after V.
584 // TODO: Add 'else' to check that DNS queries are not blocked before V.
585 if (android::modules::sdklevel::IsAtLeastV()) {
586 EXPECT_NO_FAILURE(expectQueriesAreBlocked());
587 }
588 } else {
589 // Block network access by setting UID firewall rules.
590 ScopeBlockedUIDRule scopeBlockUidRule(mDnsClient.netdService(), TEST_UID);
591 EXPECT_NO_FAILURE(expectQueriesAreBlocked());
592 }
593 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 0 /* doh */));
594 }
595 }
596
597 // Verify whether the DNS fail-fast feature can be turned off by flag.
TEST_P(TransportParameterizedTest,BlockDnsQuery_FlaggedOff)598 TEST_P(TransportParameterizedTest, BlockDnsQuery_FlaggedOff) {
599 SKIP_IF_BEFORE_T;
600 SKIP_IF_DEPENDENT_LIB_DOES_NOT_EXIST(DNS_HELPER);
601
602 constexpr char ptr_name[] = "v4v6.example.com.";
603 // PTR record for IPv6 address 2001:db8::102:304
604 constexpr char ptr_addr_v6[] =
605 "4.0.3.0.2.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.";
606 const DnsRecord r = {ptr_addr_v6, ns_type::ns_t_ptr, ptr_name};
607 dns.addMapping(r.host_name, r.type, r.addr);
608 dot_backend.addMapping(r.host_name, r.type, r.addr);
609 doh_backend.addMapping(r.host_name, r.type, r.addr);
610
611 ScopedSystemProperties sp1(kFailFastOnUidNetworkBlockingFlag, "0");
612 // TODO: Remove the flags and fix the test.
613 // Context: Fake DoT server closes SSL connection after replying to each query. But a single DNS
614 // API can send two queries for A and AAAA. One of them will failed in MTS because the current
615 // setting pushed by server is no retry.
616 ScopedSystemProperties sp2(kDotAsyncHandshakeFlag, "0");
617 ScopedSystemProperties sp3(kDotMaxretriesFlag, "3");
618
619 resetNetwork();
620
621 auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
622 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
623
624 if (testParamHasDoh()) EXPECT_TRUE(WaitForDohValidationSuccess(test::kDefaultListenAddr));
625 if (testParamHasDot()) EXPECT_TRUE(WaitForDotValidationSuccess(test::kDefaultListenAddr));
626
627 // This waiting time is expected to avoid that the DoH validation event interferes other tests.
628 if (!testParamHasDoh()) waitForDohValidationFailed();
629
630 // Have the test independent of the number of sent queries in private DNS validation, because
631 // the DnsResolver can send either 1 or 2 queries in DoT validation.
632 if (testParamHasDoh()) {
633 doh.clearQueries();
634 }
635 if (testParamHasDot()) {
636 EXPECT_TRUE(dot.waitForQueries(1));
637 dot.clearQueries();
638 }
639 dns.clearQueries();
640
641 for (const bool testDataSaver : {false, true}) {
642 SCOPED_TRACE(fmt::format("test {}", testDataSaver ? "data saver" : "UID firewall rules"));
643 if (testDataSaver) {
644 // Data Saver applies on metered networks only.
645 parcel.meteredNetwork = true;
646 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
647
648 // Block network access by enabling data saver.
649 ScopedSetDataSaverByBPF scopedSetDataSaverByBPF(true);
650 ScopedChangeUID scopedChangeUID(TEST_UID);
651 EXPECT_NO_FAILURE(sendQueryAndCheckResult());
652 } else {
653 // Block network access by setting UID firewall rules.
654 ScopeBlockedUIDRule scopeBlockUidRule(mDnsClient.netdService(), TEST_UID);
655 EXPECT_NO_FAILURE(sendQueryAndCheckResult());
656 }
657
658 if (testParamHasDoh()) {
659 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 2 /* doh */));
660 doh.clearQueries();
661 } else {
662 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 2 /* dot */, 0 /* doh */));
663 dot.clearQueries();
664 }
665 flushCache();
666 }
667 }
668
669 class PrivateDnsDohTest : public BasePrivateDnsTest {
670 protected:
SetUp()671 void SetUp() override {
672 BasePrivateDnsTest::SetUp();
673
674 ASSERT_TRUE(dns.startServer());
675 ASSERT_TRUE(dot_backend.startServer());
676 ASSERT_TRUE(dot.startServer());
677 ASSERT_TRUE(doh_backend.startServer());
678 ASSERT_TRUE(doh.startServer());
679 }
680 };
681
682 // Tests that DoH validation doesn't take much time in the following scenario:
683 // - DoH server is unreachable.
684 // - DoH server does not respond.
TEST_F(PrivateDnsDohTest,ValidationFail)685 TEST_F(PrivateDnsDohTest, ValidationFail) {
686 using std::chrono::microseconds;
687
688 constexpr milliseconds TIMING_TOLERANCE{1000};
689
690 // Make the DoT server broken so that the test can receive the validation event of both
691 // DoT and DoH, so we can calculate the time taken on DoH validation.
692 dot.stopServer();
693
694 // Set the DoH server unreachable.
695 doh.stopServer();
696
697 Stopwatch s;
698 const auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
699 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
700 EXPECT_TRUE(WaitForDohValidationFailure(test::kDefaultListenAddr));
701 EXPECT_TRUE(WaitForDotValidationFailure(test::kDefaultListenAddr));
702 EXPECT_LT(s.getTimeAndResetUs(),
703 microseconds(kExpectedDohValidationTimeWhenServerUnreachable + TIMING_TOLERANCE)
704 .count());
705
706 // Set the DoH server unresponsive.
707 ASSERT_TRUE(doh.startServer());
708 doh_backend.setResponseProbability(0.0);
709 doh_backend.setErrorRcode(static_cast<ns_rcode>(-1));
710
711 s.getTimeAndResetUs();
712 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
713 EXPECT_TRUE(WaitForDohValidationFailure(test::kDefaultListenAddr));
714 EXPECT_TRUE(WaitForDotValidationFailure(test::kDefaultListenAddr));
715 EXPECT_LT(s.getTimeAndResetUs(),
716 microseconds(kExpectedDohValidationTimeWhenTimeout + TIMING_TOLERANCE).count());
717
718 EXPECT_NO_FAILURE(sendQueryAndCheckResult());
719 EXPECT_FALSE(hasUncaughtPrivateDnsValidation(test::kDefaultListenAddr));
720 }
721
722 // Tests that DoH query fails and fallback happens.
723 // - Fallback to UDP if DoH query times out
724 // - Fallback to DoT if DoH validation is in progress or has failed.
TEST_F(PrivateDnsDohTest,QueryFailover)725 TEST_F(PrivateDnsDohTest, QueryFailover) {
726 // TODO: Remove the flags and fix the test.
727 ScopedSystemProperties sp1(kDotAsyncHandshakeFlag, "0");
728 ScopedSystemProperties sp2(kDotMaxretriesFlag, "3");
729 resetNetwork();
730
731 const auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
732 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
733 EXPECT_TRUE(WaitForDohValidationSuccess(test::kDefaultListenAddr));
734 EXPECT_TRUE(WaitForDotValidationSuccess(test::kDefaultListenAddr));
735 EXPECT_TRUE(dot.waitForQueries(1));
736 dot.clearQueries();
737 dns.clearQueries();
738
739 doh_backend.setResponseProbability(0.0);
740 doh_backend.setErrorRcode(static_cast<ns_rcode>(-1));
741
742 // Expect that the query fall back to UDP.
743 EXPECT_NO_FAILURE(sendQueryAndCheckResult());
744 EXPECT_EQ(dot.queries(), 0);
745 EXPECT_EQ(dns.queries().size(), 2U);
746 flushCache();
747
748 resetNetwork();
749 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
750
751 EXPECT_TRUE(WaitForDotValidationSuccess(test::kDefaultListenAddr));
752 EXPECT_TRUE(dot.waitForQueries(1));
753 dot.clearQueries();
754 dns.clearQueries();
755
756 // Expect that the query fall back to DoT as DoH validation is in progress.
757 EXPECT_NO_FAILURE(sendQueryAndCheckResult());
758
759 EXPECT_EQ(dot.queries(), 2);
760 EXPECT_EQ(dns.queries().size(), 0U);
761 waitForDohValidationTimeout();
762 flushCache();
763
764 // Expect that this query fall back to DoT as DoH validation has failed.
765 EXPECT_NO_FAILURE(sendQueryAndCheckResult());
766 EXPECT_EQ(dot.queries(), 4);
767 EXPECT_EQ(dns.queries().size(), 0U);
768 }
769
770 // Tests that the DnsResolver prioritizes IPv6 DoH servers over IPv4 DoH servers.
TEST_F(PrivateDnsDohTest,PreferIpv6)771 TEST_F(PrivateDnsDohTest, PreferIpv6) {
772 constexpr char listen_ipv6_addr[] = "::1";
773 const std::vector<std::vector<std::string>> testConfig = {
774 {test::kDefaultListenAddr, listen_ipv6_addr},
775 {listen_ipv6_addr, test::kDefaultListenAddr},
776 };
777
778 // To simplify the test, set the DoT server broken.
779 dot.stopServer();
780
781 test::DNSResponder dns_ipv6{listen_ipv6_addr, kDnsPortString};
782 test::DohFrontend doh_ipv6{listen_ipv6_addr, kDohPortString, listen_ipv6_addr, kDnsPortString};
783 dns_ipv6.addMapping(kQueryHostname, ns_type::ns_t_a, kQueryAnswerA);
784 dns_ipv6.addMapping(kQueryHostname, ns_type::ns_t_aaaa, kQueryAnswerAAAA);
785 ASSERT_TRUE(dns_ipv6.startServer());
786 ASSERT_TRUE(doh_ipv6.startServer());
787
788 for (const auto& serverList : testConfig) {
789 SCOPED_TRACE(fmt::format("serverList: [{}]", fmt::join(serverList, ", ")));
790
791 auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
792 parcel.servers = serverList;
793 parcel.tlsServers = serverList;
794 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
795
796 // Currently, DnsResolver sorts the server list and did DoH validation only
797 // for the first server.
798 EXPECT_TRUE(WaitForDohValidationSuccess(listen_ipv6_addr));
799
800 doh.clearQueries();
801 doh_ipv6.clearQueries();
802
803 EXPECT_NO_FAILURE(sendQueryAndCheckResult());
804 EXPECT_EQ(doh_ipv6.queries(), 2);
805 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 0 /* doh */));
806
807 resetNetwork();
808 }
809 }
810
811 // Tests that DoH server setting can be replaced/removed correctly.
TEST_F(PrivateDnsDohTest,ChangeAndClearPrivateDnsServer)812 TEST_F(PrivateDnsDohTest, ChangeAndClearPrivateDnsServer) {
813 constexpr char listen_ipv6_addr[] = "::1";
814
815 // To simplify the test, set the DoT server broken.
816 dot.stopServer();
817
818 test::DNSResponder dns_ipv6{listen_ipv6_addr, kDnsPortString};
819 test::DohFrontend doh_ipv6{listen_ipv6_addr, kDohPortString, listen_ipv6_addr, kDnsPortString};
820 dns_ipv6.addMapping(kQueryHostname, ns_type::ns_t_a, kQueryAnswerA);
821 dns_ipv6.addMapping(kQueryHostname, ns_type::ns_t_aaaa, kQueryAnswerAAAA);
822 ASSERT_TRUE(dns_ipv6.startServer());
823 ASSERT_TRUE(doh_ipv6.startServer());
824
825 auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
826 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
827
828 // Use v4 DoH server first.
829 EXPECT_TRUE(WaitForDohValidationSuccess(test::kDefaultListenAddr));
830 doh.clearQueries();
831 EXPECT_NO_FAILURE(sendQueryAndCheckResult());
832 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 2 /* doh */));
833
834 // Change to the v6 DoH server.
835 parcel.servers = {listen_ipv6_addr};
836 parcel.tlsServers = {listen_ipv6_addr};
837 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
838 EXPECT_TRUE(WaitForDohValidationSuccess(listen_ipv6_addr));
839 doh.clearQueries();
840 doh_ipv6.clearQueries();
841 flushCache();
842 EXPECT_NO_FAILURE(sendQueryAndCheckResult());
843 EXPECT_EQ(doh_ipv6.queries(), 2);
844 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 0 /* doh */));
845
846 // Change to an invalid DoH server.
847 parcel.tlsServers = {kHelloExampleComAddrV4};
848 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
849 doh_ipv6.clearQueries();
850 dns_ipv6.clearQueries();
851 flushCache();
852 EXPECT_NO_FAILURE(sendQueryAndCheckResult());
853 EXPECT_EQ(doh_ipv6.queries(), 0);
854 EXPECT_EQ(dns_ipv6.queries().size(), 2U);
855
856 // Remove private DNS servers.
857 parcel.tlsServers = {};
858 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
859 doh_ipv6.clearQueries();
860 dns_ipv6.clearQueries();
861 flushCache();
862 EXPECT_NO_FAILURE(sendQueryAndCheckResult());
863 EXPECT_EQ(doh_ipv6.queries(), 0);
864 EXPECT_EQ(dns_ipv6.queries().size(), 2U);
865 }
866
TEST_F(PrivateDnsDohTest,ChangePrivateDnsServerAndVerifyOutput)867 TEST_F(PrivateDnsDohTest, ChangePrivateDnsServerAndVerifyOutput) {
868 // To simplify the test, set the DoT server broken.
869 dot.stopServer();
870
871 static const std::string ipv4DohServerAddr = "127.0.0.3";
872 static const std::string ipv6DohServerAddr = "::1";
873
874 test::DNSResponder dns_ipv6{ipv6DohServerAddr, kDnsPortString};
875 test::DohFrontend doh_ipv6{ipv6DohServerAddr, kDohPortString, ipv6DohServerAddr,
876 kDnsPortString};
877 dns.addMapping(kQueryHostname, ns_type::ns_t_a, kQueryAnswerA);
878 dns.addMapping(kQueryHostname, ns_type::ns_t_aaaa, kQueryAnswerAAAA);
879 dns_ipv6.addMapping(kQueryHostname, ns_type::ns_t_a, kQueryAnswerA);
880 dns_ipv6.addMapping(kQueryHostname, ns_type::ns_t_aaaa, kQueryAnswerAAAA);
881 ASSERT_TRUE(dns_ipv6.startServer());
882 ASSERT_TRUE(doh_ipv6.startServer());
883
884 // Start the v4 DoH server.
885 auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
886 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
887 EXPECT_TRUE(WaitForDohValidationSuccess(test::kDefaultListenAddr));
888 EXPECT_TRUE(expectLog(ipv4DohServerAddr, kDohPortString));
889
890 // Change to an invalid DoH server.
891 parcel.tlsServers = {kHelloExampleComAddrV4};
892 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
893 EXPECT_FALSE(expectLog(kHelloExampleComAddrV4, kDohPortString));
894 EXPECT_TRUE(expectLog("<no data>", ""));
895
896 // Change to the v6 DoH server.
897 parcel.servers = {ipv6DohServerAddr};
898 parcel.tlsServers = {ipv6DohServerAddr};
899 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
900 EXPECT_TRUE(WaitForDohValidationSuccess(ipv6DohServerAddr));
901 EXPECT_TRUE(expectLog(ipv6DohServerAddr, kDohPortString));
902 EXPECT_FALSE(expectLog(ipv4DohServerAddr, kDohPortString));
903
904 // Remove the private DNS server.
905 parcel.tlsServers = {};
906 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
907 EXPECT_FALSE(expectLog(ipv4DohServerAddr, kDohPortString));
908 EXPECT_FALSE(expectLog(ipv6DohServerAddr, kDohPortString));
909 EXPECT_TRUE(expectLog("<no data>", ""));
910 }
911
912 // Tests that a DoH query is sent while the network is stalled temporarily.
TEST_F(PrivateDnsDohTest,TemporaryConnectionStalled)913 TEST_F(PrivateDnsDohTest, TemporaryConnectionStalled) {
914 const int connectionStalledTimeMs = 3000;
915 ScopedSystemProperties sp(kDohQueryTimeoutFlag, "10000");
916 resetNetwork();
917
918 const auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
919 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
920 EXPECT_TRUE(WaitForDohValidationSuccess(test::kDefaultListenAddr));
921 EXPECT_TRUE(WaitForDotValidationSuccess(test::kDefaultListenAddr));
922 EXPECT_TRUE(dot.waitForQueries(1));
923 dot.clearQueries();
924 doh.clearQueries();
925 dns.clearQueries();
926
927 EXPECT_TRUE(doh.block_sending(true));
928 Stopwatch s;
929 int fd = resNetworkQuery(TEST_NETID, kQueryHostname, ns_c_in, ns_t_a,
930 ANDROID_RESOLV_NO_CACHE_LOOKUP);
931 sleep_for(milliseconds(connectionStalledTimeMs));
932 EXPECT_TRUE(doh.block_sending(false));
933
934 expectAnswersValid(fd, AF_INET, kQueryAnswerA);
935 EXPECT_GT(s.timeTakenUs() / 1000, connectionStalledTimeMs);
936 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 1 /* doh */));
937 }
938
939 // (b/207301204): Tests that the DnsResolver will try DoT rather than DoH if there are excess
940 // DNS requests. In addition, tests that sending DNS requests to other networks succeeds.
941 // Note: This test is subject to MAX_BUFFERED_COMMANDS. If the value is changed, this test might
942 // need to be modified as well.
TEST_F(PrivateDnsDohTest,ExcessDnsRequests)943 TEST_F(PrivateDnsDohTest, ExcessDnsRequests) {
944 const int total_queries = 70;
945
946 // In most cases, the number of timed-out DoH queries is MAX_BUFFERED_COMMANDS + 2 (one that
947 // will be queued in connection's mpsc::channel; the other one that will get blocked at
948 // dispatcher's mpsc::channel), as shown below:
949 //
950 // dispatcher's mpsc::channel -----> network's mpsc:channel -----> connection's mpsc::channel
951 // (expect 1 query queued here) (size: MAX_BUFFERED_COMMANDS) (expect 1 query queued here)
952 //
953 // However, it's still possible that the (MAX_BUFFERED_COMMANDS + 2)th query is sent to the DoH
954 // engine before the DoH engine moves a query to connection's mpsc::channel. In that case,
955 // the (MAX_BUFFERED_COMMANDS + 2)th query will be fallback'ed to DoT immediately rather than
956 // be waiting until DoH timeout, which result in only (MAX_BUFFERED_COMMANDS + 1) timed-out
957 // DoH queries.
958 const int doh_timeout_queries = 52;
959
960 // If early data flag is enabled, DnsResolver doesn't wait for the connection established.
961 // It will send DNS queries along with 0-RTT rather than queue them in connection mpsc channel.
962 // So we disable the flag.
963 ScopedSystemProperties sp(kDohEarlyDataFlag, "0");
964 resetNetwork();
965
966 const int initial_max_idle_timeout_ms = 2000;
967 ASSERT_TRUE(doh.stopServer());
968 EXPECT_TRUE(doh.setMaxIdleTimeout(initial_max_idle_timeout_ms));
969 ASSERT_TRUE(doh.startServer());
970
971 auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
972 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
973 EXPECT_TRUE(WaitForDohValidationSuccess(test::kDefaultListenAddr));
974 EXPECT_TRUE(WaitForDotValidationSuccess(test::kDefaultListenAddr));
975 EXPECT_TRUE(dot.waitForQueries(1));
976 dot.clearQueries();
977 doh.clearQueries();
978 dns.clearQueries();
979
980 // Set the DoT server not to close the connection until it receives enough queries or timeout.
981 dot.setDelayQueries(total_queries - doh_timeout_queries);
982 dot.setDelayQueriesTimeout(200);
983
984 // Set the server blocking, wait for the connection closed, and send some DNS requests.
985 EXPECT_TRUE(doh.block_sending(true));
986 EXPECT_TRUE(doh.waitForAllClientsDisconnected());
987 std::array<int, total_queries> fds;
988 for (auto& fd : fds) {
989 fd = resNetworkQuery(TEST_NETID, kQueryHostname, ns_c_in, ns_t_aaaa,
990 ANDROID_RESOLV_NO_CACHE_LOOKUP);
991 }
992 for (const auto& fd : fds) {
993 expectAnswersValid(fd, AF_INET6, kQueryAnswerAAAA);
994 }
995 EXPECT_TRUE(doh.block_sending(false));
996
997 // There are some queries that fall back to DoT rather than UDP since the DoH client rejects
998 // any new DNS requests when the capacity is full.
999 EXPECT_THAT(dns.queries().size(), AnyOf(doh_timeout_queries, doh_timeout_queries - 1));
1000 EXPECT_THAT(dot.queries(), AnyOf(total_queries - doh_timeout_queries,
1001 total_queries - doh_timeout_queries + 1));
1002 EXPECT_EQ(doh.queries(), 0);
1003
1004 // Set up another network and send a DNS query. Expect that this network is unaffected.
1005 constexpr int TEST_NETID_2 = 31;
1006 constexpr char listen_ipv6_addr[] = "::1";
1007 test::DNSResponder dns_ipv6{listen_ipv6_addr, kDnsPortString};
1008 test::DnsTlsFrontend dot_ipv6{listen_ipv6_addr, kDotPortString, listen_ipv6_addr,
1009 kDnsPortString};
1010 test::DohFrontend doh_ipv6{listen_ipv6_addr, kDohPortString, listen_ipv6_addr, kDnsPortString};
1011
1012 dns_ipv6.addMapping(kQueryHostname, ns_type::ns_t_aaaa, kQueryAnswerAAAA);
1013 ASSERT_TRUE(dns_ipv6.startServer());
1014 ASSERT_TRUE(dot_ipv6.startServer());
1015 ASSERT_TRUE(doh_ipv6.startServer());
1016
1017 mDnsClient.SetupOemNetwork(TEST_NETID_2);
1018 parcel.netId = TEST_NETID_2;
1019 parcel.servers = {listen_ipv6_addr};
1020 parcel.tlsServers = {listen_ipv6_addr};
1021 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
1022
1023 // Sleep a while to wait for DoH and DoT validation.
1024 // TODO: Extend WaitForDohValidation() to support passing a netId.
1025 sleep_for(milliseconds(200));
1026 EXPECT_TRUE(dot_ipv6.waitForQueries(1));
1027
1028 int fd = resNetworkQuery(TEST_NETID_2, kQueryHostname, ns_c_in, ns_t_aaaa,
1029 ANDROID_RESOLV_NO_CACHE_LOOKUP);
1030 expectAnswersValid(fd, AF_INET6, kQueryAnswerAAAA);
1031
1032 // Expect two queries: one for DoH probe and the other one for kQueryHostname.
1033 EXPECT_EQ(doh_ipv6.queries(), 2);
1034
1035 mDnsClient.TearDownOemNetwork(TEST_NETID_2);
1036
1037 // The DnsResolver will reconnect to the DoH server for the query that gets blocked at
1038 // dispatcher sending channel. However, there's no way to know when the reconnection will start.
1039 // We have to periodically send a DNS request to check it. After the reconnection starts, the
1040 // DNS query will be sent to the Doh server instead of the cleartext DNS server. Then, we
1041 // are safe to end the test. Otherwise, the reconnection will interfere other tests.
1042 EXPECT_EQ(doh.queries(), 0);
1043 for (int i = 0; i < 50; i++) {
1044 sleep_for(milliseconds(100));
1045 int fd = resNetworkQuery(TEST_NETID, kQueryHostname, ns_c_in, ns_t_aaaa,
1046 ANDROID_RESOLV_NO_CACHE_LOOKUP);
1047 expectAnswersValid(fd, AF_INET6, kQueryAnswerAAAA);
1048 if (doh.queries() > 0) break;
1049 }
1050 EXPECT_GT(doh.queries(), 0);
1051 }
1052
1053 // Tests the scenario where the DnsResolver runs out of QUIC connection data limit.
TEST_F(PrivateDnsDohTest,RunOutOfDataLimit)1054 TEST_F(PrivateDnsDohTest, RunOutOfDataLimit) {
1055 // Each DoH query consumes about 100 bytes of QUIC connection send capacity.
1056 // Set initial_max_data to 450 so the fifth DoH query will get blocked.
1057 const int queries = 4;
1058 const int initial_max_data = 450;
1059
1060 ScopedSystemProperties sp(kDohQueryTimeoutFlag, "3000");
1061 resetNetwork();
1062
1063 ASSERT_TRUE(doh.stopServer());
1064 EXPECT_TRUE(doh.setMaxBufferSize(initial_max_data));
1065 ASSERT_TRUE(doh.startServer());
1066
1067 const auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
1068 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
1069 EXPECT_TRUE(WaitForDohValidationSuccess(test::kDefaultListenAddr));
1070 EXPECT_TRUE(WaitForDotValidationSuccess(test::kDefaultListenAddr));
1071 EXPECT_TRUE(dot.waitForQueries(1));
1072 dot.clearQueries();
1073 doh.clearQueries();
1074 dns.clearQueries();
1075
1076 // Block the DoH server from sending data for a while.
1077 EXPECT_TRUE(doh.block_sending(true));
1078 std::vector<std::thread> threads(queries);
1079 for (std::thread& thread : threads) {
1080 thread = std::thread([&]() {
1081 int fd = resNetworkQuery(TEST_NETID, kQueryHostname, ns_c_in, ns_t_a,
1082 ANDROID_RESOLV_NO_CACHE_LOOKUP);
1083 expectAnswersValid(fd, AF_INET, kQueryAnswerA);
1084 });
1085 }
1086 sleep_for(milliseconds(500));
1087 EXPECT_TRUE(doh.block_sending(false));
1088
1089 // In current implementation, the fifth DoH query will get blocked and result in timeout.
1090 int fd = resNetworkQuery(TEST_NETID, kQueryHostname, ns_c_in, ns_t_a,
1091 ANDROID_RESOLV_NO_CACHE_LOOKUP);
1092 expectAnswersValid(fd, AF_INET, kQueryAnswerA);
1093
1094 for (std::thread& thread : threads) {
1095 thread.join();
1096 }
1097
1098 // TODO: see how we can improve the DnsResolver to make all of the DNS queries resolved by DoH.
1099 // EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 5 /* doh */));
1100 }
1101
1102 // Tests the scenario where the DnsResolver runs out of QUIC streams limit.
TEST_F(PrivateDnsDohTest,RunOutOfStreams)1103 TEST_F(PrivateDnsDohTest, RunOutOfStreams) {
1104 const int queries = 6;
1105 const int initial_max_streams_bidi = 5;
1106
1107 // Since the last query won't be issued until there are streams available, lengthen the
1108 // timeout to 3 seconds.
1109 ScopedSystemProperties sp(kDohQueryTimeoutFlag, "3000");
1110 resetNetwork();
1111
1112 ASSERT_TRUE(doh.stopServer());
1113 EXPECT_TRUE(doh.setMaxStreamsBidi(initial_max_streams_bidi));
1114 ASSERT_TRUE(doh.startServer());
1115
1116 const auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
1117 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
1118 EXPECT_TRUE(WaitForDohValidationSuccess(test::kDefaultListenAddr));
1119 EXPECT_TRUE(WaitForDotValidationSuccess(test::kDefaultListenAddr));
1120 EXPECT_TRUE(dot.waitForQueries(1));
1121 dot.clearQueries();
1122 doh.clearQueries();
1123 dns.clearQueries();
1124
1125 // Block the DoH server from sending data for a while.
1126 EXPECT_TRUE(doh.block_sending(true));
1127 std::vector<std::thread> threads(queries);
1128 for (std::thread& thread : threads) {
1129 thread = std::thread([&]() {
1130 int fd = resNetworkQuery(TEST_NETID, kQueryHostname, ns_c_in, ns_t_a,
1131 ANDROID_RESOLV_NO_CACHE_LOOKUP);
1132 expectAnswersValid(fd, AF_INET, kQueryAnswerA);
1133 });
1134 }
1135 sleep_for(milliseconds(500));
1136 EXPECT_TRUE(doh.block_sending(false));
1137
1138 for (std::thread& thread : threads) {
1139 thread.join();
1140 }
1141
1142 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 6 /* doh */));
1143 }
1144
1145 // Tests that the DnsResolver automatically reconnects to the DoH server when needed.
1146 // Session resumption should be used in each reconnection.
TEST_F(PrivateDnsDohTest,ReconnectAfterIdleTimeout)1147 TEST_F(PrivateDnsDohTest, ReconnectAfterIdleTimeout) {
1148 const int initial_max_idle_timeout_ms = 1000;
1149
1150 ASSERT_TRUE(doh.stopServer());
1151 EXPECT_TRUE(doh.setMaxIdleTimeout(initial_max_idle_timeout_ms));
1152 ASSERT_TRUE(doh.startServer());
1153
1154 const auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
1155 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
1156 EXPECT_TRUE(WaitForDohValidationSuccess(test::kDefaultListenAddr));
1157 EXPECT_TRUE(WaitForDotValidationSuccess(test::kDefaultListenAddr));
1158 EXPECT_TRUE(dot.waitForQueries(1));
1159 dot.clearQueries();
1160 doh.clearQueries();
1161 dns.clearQueries();
1162
1163 for (int i = 0; i < 5; i++) {
1164 SCOPED_TRACE(fmt::format("Round: {}", i));
1165 sleep_for(milliseconds(initial_max_idle_timeout_ms + 500));
1166
1167 // As the connection is closed, the DnsResolver will reconnect to the DoH server
1168 // for this DNS request.
1169 int fd = resNetworkQuery(TEST_NETID, kQueryHostname, ns_c_in, ns_t_a,
1170 ANDROID_RESOLV_NO_CACHE_LOOKUP);
1171 expectAnswersValid(fd, AF_INET, kQueryAnswerA);
1172 }
1173
1174 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 5 /* doh */));
1175 EXPECT_EQ(doh.connections(), 6);
1176 }
1177
1178 // Tests that the experiment flag doh_idle_timeout_ms is effective.
TEST_F(PrivateDnsDohTest,ConnectionIdleTimer)1179 TEST_F(PrivateDnsDohTest, ConnectionIdleTimer) {
1180 const int connection_idle_timeout = 1500;
1181 const int tolerance_ms = 200;
1182
1183 // Check if the default value or the timeout the device is using is too short for the test.
1184 const int device_connection_idle_timeout =
1185 std::min(std::stoi(GetProperty(kDohIdleTimeoutFlag, "9999")), kDohIdleDefaultTimeoutMs);
1186 if (device_connection_idle_timeout <= connection_idle_timeout + tolerance_ms) {
1187 GTEST_LOG_(INFO) << "The test can't guarantee that the flag takes effect because "
1188 << "device_connection_idle_timeout is too short: "
1189 << device_connection_idle_timeout << " ms.";
1190 }
1191
1192 ScopedSystemProperties sp(kDohIdleTimeoutFlag, std::to_string(connection_idle_timeout));
1193 resetNetwork();
1194
1195 const auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
1196 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
1197 EXPECT_TRUE(WaitForDohValidationSuccess(test::kDefaultListenAddr));
1198 EXPECT_TRUE(WaitForDotValidationSuccess(test::kDefaultListenAddr));
1199 EXPECT_TRUE(dot.waitForQueries(1));
1200 dot.clearQueries();
1201 doh.clearQueries();
1202 dns.clearQueries();
1203
1204 EXPECT_NO_FAILURE(sendQueryAndCheckResult());
1205 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 2 /* doh */));
1206 flushCache();
1207 EXPECT_EQ(doh.connections(), 1);
1208
1209 // Expect that the DoH connection gets disconnected while sleeping.
1210 sleep_for(milliseconds(connection_idle_timeout + tolerance_ms));
1211
1212 EXPECT_NO_FAILURE(sendQueryAndCheckResult());
1213 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 4 /* doh */));
1214 EXPECT_EQ(doh.connections(), 2);
1215 }
1216
1217 // Tests that the flag "doh_session_resumption" works as expected.
TEST_F(PrivateDnsDohTest,SessionResumption)1218 TEST_F(PrivateDnsDohTest, SessionResumption) {
1219 const int initial_max_idle_timeout_ms = 1000;
1220 for (const auto& flag : {"0", "1"}) {
1221 SCOPED_TRACE(fmt::format("flag: {}", flag));
1222 ScopedSystemProperties sp(kDohSessionResumptionFlag, flag);
1223 resetNetwork();
1224
1225 ASSERT_TRUE(doh.stopServer());
1226 EXPECT_TRUE(doh.setMaxIdleTimeout(initial_max_idle_timeout_ms));
1227 ASSERT_TRUE(doh.startServer());
1228
1229 const auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
1230 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
1231 EXPECT_TRUE(WaitForDohValidationSuccess(test::kDefaultListenAddr));
1232 EXPECT_TRUE(WaitForDotValidationSuccess(test::kDefaultListenAddr));
1233 EXPECT_TRUE(dot.waitForQueries(1));
1234 dot.clearQueries();
1235 doh.clearQueries();
1236 dns.clearQueries();
1237
1238 for (int i = 0; i < 2; i++) {
1239 SCOPED_TRACE(fmt::format("Round: {}", i));
1240 sleep_for(milliseconds(initial_max_idle_timeout_ms + 500));
1241
1242 // As the connection is closed, the DnsResolver will reconnect to the DoH server
1243 // for this DNS request.
1244 int fd = resNetworkQuery(TEST_NETID, kQueryHostname, ns_c_in, ns_t_a,
1245 ANDROID_RESOLV_NO_CACHE_LOOKUP);
1246 expectAnswersValid(fd, AF_INET, kQueryAnswerA);
1247 }
1248
1249 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 2 /* doh */));
1250 EXPECT_EQ(doh.connections(), 3);
1251 EXPECT_EQ(doh.resumedConnections(), (strcmp(flag, "1") ? 0 : 2));
1252 }
1253 }
1254
1255 // Tests that the flag "doh_early_data" works as expected.
TEST_F(PrivateDnsDohTest,TestEarlyDataFlag)1256 TEST_F(PrivateDnsDohTest, TestEarlyDataFlag) {
1257 const int initial_max_idle_timeout_ms = 1000;
1258 for (const auto& flag : {"0", "1"}) {
1259 SCOPED_TRACE(fmt::format("flag: {}", flag));
1260 ScopedSystemProperties sp1(kDohSessionResumptionFlag, flag);
1261 ScopedSystemProperties sp2(kDohEarlyDataFlag, flag);
1262 resetNetwork();
1263
1264 ASSERT_TRUE(doh.stopServer());
1265 EXPECT_TRUE(doh.setMaxIdleTimeout(initial_max_idle_timeout_ms));
1266 ASSERT_TRUE(doh.startServer());
1267
1268 const auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
1269 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
1270 EXPECT_TRUE(WaitForDohValidationSuccess(test::kDefaultListenAddr));
1271 EXPECT_TRUE(WaitForDotValidationSuccess(test::kDefaultListenAddr));
1272 EXPECT_TRUE(dot.waitForQueries(1));
1273 dot.clearQueries();
1274 doh.clearQueries();
1275 dns.clearQueries();
1276
1277 // Wait for the connection closed, and then send a DNS query.
1278 // Expect the query to be sent in early data if the flag is on.
1279 sleep_for(milliseconds(initial_max_idle_timeout_ms + 500));
1280 int fd = resNetworkQuery(TEST_NETID, kQueryHostname, ns_c_in, ns_t_aaaa,
1281 ANDROID_RESOLV_NO_CACHE_LOOKUP);
1282 expectAnswersValid(fd, AF_INET6, kQueryAnswerAAAA);
1283 EXPECT_EQ(doh.earlyDataConnections(), (strcmp(flag, "1") ? 0 : 1));
1284 }
1285 }
1286
1287 // Tests that after the connection is closed by the server (known by sending CONNECTION_CLOSE
1288 // frame), the DnsResolver can initiate another new connection for DNS requests.
TEST_F(PrivateDnsDohTest,RemoteConnectionClosed)1289 TEST_F(PrivateDnsDohTest, RemoteConnectionClosed) {
1290 const auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
1291 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
1292 EXPECT_TRUE(WaitForDohValidationSuccess(test::kDefaultListenAddr));
1293 EXPECT_TRUE(WaitForDotValidationSuccess(test::kDefaultListenAddr));
1294 EXPECT_TRUE(dot.waitForQueries(1));
1295 dot.clearQueries();
1296 doh.clearQueries();
1297 dns.clearQueries();
1298
1299 EXPECT_NO_FAILURE(sendQueryAndCheckResult());
1300 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 2 /* doh */));
1301 flushCache();
1302 EXPECT_EQ(doh.connections(), 1);
1303
1304 // Make the server close the connection. This will also reset the stats, so the doh query
1305 // count below is still 2 rather than 4.
1306 ASSERT_TRUE(doh.stopServer());
1307 ASSERT_TRUE(doh.startServer());
1308
1309 EXPECT_NO_FAILURE(sendQueryAndCheckResult());
1310 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 2 /* doh */));
1311 EXPECT_EQ(doh.connections(), 1);
1312 }
1313
1314 // Tests that a DNS query can quickly fall back from DoH to other dns protocols if server responds
1315 // the DNS query with RESET_STREAM, and that it doesn't influence subsequent DoH queries.
TEST_F(PrivateDnsDohTest,ReceiveResetStream)1316 TEST_F(PrivateDnsDohTest, ReceiveResetStream) {
1317 const auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
1318 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
1319 EXPECT_TRUE(WaitForDohValidationSuccess(test::kDefaultListenAddr));
1320 EXPECT_TRUE(WaitForDotValidationSuccess(test::kDefaultListenAddr));
1321 EXPECT_TRUE(dot.waitForQueries(1));
1322 dot.clearQueries();
1323 doh.clearQueries();
1324 dns.clearQueries();
1325
1326 // DnsResolver uses bidirectional streams for DoH queries (See
1327 // RFC9000#name-stream-types-and-identifier), and stream 0 has been used for DoH probe, so
1328 // the next stream for the next DoH query will be 4.
1329 EXPECT_TRUE(doh.setResetStreamId(4));
1330
1331 // Send a DNS request. The DoH query will be sent on stream 4 and fail.
1332 Stopwatch s;
1333 int fd = resNetworkQuery(TEST_NETID, kQueryHostname, ns_c_in, ns_t_aaaa,
1334 ANDROID_RESOLV_NO_CACHE_LOOKUP);
1335 expectAnswersValid(fd, AF_INET6, kQueryAnswerAAAA);
1336 EXPECT_LT(s.timeTakenUs() / 1000, 500);
1337 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 1 /* dot */, 1 /* doh */));
1338
1339 // Send another DNS request. The DoH query will be sent on stream 8 and succeed.
1340 fd = resNetworkQuery(TEST_NETID, kQueryHostname, ns_c_in, ns_t_aaaa,
1341 ANDROID_RESOLV_NO_CACHE_LOOKUP);
1342 expectAnswersValid(fd, AF_INET6, kQueryAnswerAAAA);
1343 EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 1 /* dot */, 2 /* doh */));
1344 }
1345
1346 // Tests that, given an IP address with an allowed DoH provider name, PrivateDnsConfiguration
1347 // attempts to probe the server for DoH.
1348 // This test is representative of DoH using DDR in opportunistic mode.
TEST_F(PrivateDnsDohTest,UseDohAsLongAsHostnameMatch)1349 TEST_F(PrivateDnsDohTest, UseDohAsLongAsHostnameMatch) {
1350 // "example.com" is an allowed DoH provider name defined in
1351 // PrivateDnsConfiguration::mAvailableDoHProviders.
1352 constexpr char allowedDohName[] = "example.com";
1353 constexpr char someOtherIp[] = "127.99.99.99";
1354
1355 // The test currently doesn't support testing DoH in private DNS strict mode, so DnsResolver
1356 // can't connect to the testing DoH servers. We use onPrivateDnsValidationEvent() to check
1357 // whether DoT/DoH probes are performed.
1358 // Without an allowed private DNS provider hostname, expect PrivateDnsConfiguration to probe
1359 // the server for DoT only.
1360 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(
1361 ResolverParams::Builder().setDotServers({someOtherIp}).build()));
1362 EXPECT_TRUE(WaitForDotValidationFailure(someOtherIp));
1363 EXPECT_FALSE(hasUncaughtPrivateDnsValidation(someOtherIp));
1364
1365 // With an allowed private DNS provider hostname, expect PrivateDnsConfiguration to probe the
1366 // server for both DoT and DoH.
1367 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(ResolverParams::Builder()
1368 .setDotServers({someOtherIp})
1369 .setPrivateDnsProvider(allowedDohName)
1370 .build()));
1371 EXPECT_TRUE(WaitForDotValidationFailure(someOtherIp));
1372 EXPECT_TRUE(WaitForDohValidationFailure(someOtherIp));
1373
1374 // Disable DoT and DoH. This ensures that when DoT is re-enabled right afterwards, the test
1375 // observes a validation failure.
1376 ASSERT_TRUE(
1377 mDnsClient.SetResolversFromParcel(ResolverParams::Builder().setDotServers({}).build()));
1378
1379 // If DDR is enabled and reports no results (empty DoH params), don't probe for DoH.
1380 DohParamsParcel emptyDohParams = {};
1381 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(ResolverParams::Builder()
1382 .setDotServers({someOtherIp})
1383 .setPrivateDnsProvider(allowedDohName)
1384 .setDohParams(emptyDohParams)
1385 .build()));
1386 EXPECT_TRUE(WaitForDotValidationFailure(someOtherIp));
1387 EXPECT_FALSE(WaitForDohValidationFailure(someOtherIp));
1388
1389 EXPECT_FALSE(hasUncaughtPrivateDnsValidation(someOtherIp));
1390 }
1391
1392 // Tests that if DDR is enabled, but returns no parameters, that DoH is not enabled.
TEST_F(PrivateDnsDohTest,DdrEnabledButNoResponse)1393 TEST_F(PrivateDnsDohTest, DdrEnabledButNoResponse) {
1394 // "example.com" is an allowed DoH provider name defined in
1395 // PrivateDnsConfiguration::mAvailableDoHProviders.
1396 constexpr char allowedDohName[] = "example.com";
1397 constexpr char someOtherIp[] = "127.99.99.99";
1398
1399 // If DDR is enabled and reports no results (empty DoH params), don't probe for DoH.
1400 DohParamsParcel emptyDohParams = {};
1401 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(ResolverParams::Builder()
1402 .setDotServers({someOtherIp})
1403 .setPrivateDnsProvider(allowedDohName)
1404 .setDohParams(emptyDohParams)
1405 .build()));
1406 EXPECT_TRUE(WaitForDotValidationFailure(someOtherIp));
1407 EXPECT_FALSE(WaitForDohValidationFailure(someOtherIp));
1408
1409 EXPECT_FALSE(hasUncaughtPrivateDnsValidation(someOtherIp));
1410 }
1411 // Tests DoH with a hostname.
1412 // This test is representative of DoH using DDR in strict mode.
TEST_F(PrivateDnsDohTest,DohParamsParcel)1413 TEST_F(PrivateDnsDohTest, DohParamsParcel) {
1414 // Because the test doesn't support serving DoH in strict mode, it cannot check for actual DoH
1415 // queries, it can only check for validation attempts.
1416 constexpr char name[] = "example.com";
1417 constexpr char dohIp[] = "127.99.99.99";
1418 DohParamsParcel dohParams = {
1419 .name = name,
1420 .ips = {dohIp},
1421 .dohpath = "/dns-query{?dns}",
1422 .port = 443,
1423 };
1424
1425 // Only DoH enabled.
1426 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(
1427 ResolverParams::Builder().setDohParams(dohParams).build()));
1428 EXPECT_FALSE(WaitForDotValidationFailure(dohIp));
1429 EXPECT_TRUE(WaitForDohValidationFailure(dohIp));
1430
1431 // Both DoT and DoH enabled.
1432 constexpr char dotIp[] = "127.88.88.88";
1433 ASSERT_TRUE(mDnsClient.SetResolversFromParcel(ResolverParams::Builder()
1434 .setPrivateDnsProvider(name)
1435 .setDotServers({dotIp})
1436 .setDohParams(dohParams)
1437 .build()));
1438 EXPECT_TRUE(WaitForDotValidationFailure(dotIp));
1439 EXPECT_TRUE(WaitForDohValidationFailure(dohIp));
1440
1441 EXPECT_FALSE(hasUncaughtPrivateDnsValidation(dohIp));
1442 EXPECT_FALSE(hasUncaughtPrivateDnsValidation(dotIp));
1443 }
1444