blob: 2e7187322d8364b8e99bea3d5307e765ef6283c2 [file] [log] [blame]
Hungming Chenf9cd4eb2019-08-06 20:55:28 +09001/*
2 * Copyright (C) 2019 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_gold_test"
19
Hungming Chenc6556622019-10-02 16:01:07 +080020#include <Fwmark.h>
21#include <android-base/chrono_utils.h>
Hungming Chen21c0f832019-09-20 18:38:47 +080022#include <android-base/file.h>
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090023#include <gmock/gmock-matchers.h>
Hungming Chen21c0f832019-09-20 18:38:47 +080024#include <google/protobuf/text_format.h>
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090025#include <gtest/gtest.h>
26
Hungming Chenc6556622019-10-02 16:01:07 +080027#include "PrivateDnsConfiguration.h"
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090028#include "dns_responder/dns_responder.h"
Hungming Chenc6556622019-10-02 16:01:07 +080029#include "dns_responder_client.h"
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090030#include "getaddrinfo.h"
Hungming Chen21c0f832019-09-20 18:38:47 +080031#include "golddata.pb.h"
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090032#include "resolv_cache.h"
33#include "resolv_test_utils.h"
Hungming Chenc6556622019-10-02 16:01:07 +080034#include "tests/dns_responder/dns_tls_certificate.h"
35#include "tests/dns_responder/dns_tls_frontend.h"
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090036
37namespace android {
38namespace net {
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090039using android::netdutils::ScopedAddrinfo;
Hungming Chenc6556622019-10-02 16:01:07 +080040using std::chrono::milliseconds;
41
42const std::string kTestDataPath = android::base::GetExecutableDirectory() + "/testdata/";
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090043
Hungming Chen21c0f832019-09-20 18:38:47 +080044// Fixture test class definition.
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090045class TestBase : public ::testing::Test {
46 protected:
47 void SetUp() override {
48 // Create cache for test
49 resolv_create_cache_for_net(TEST_NETID);
50 }
51
52 void TearDown() override {
Hungming Chenc6556622019-10-02 16:01:07 +080053 // Clear TLS configuration for test
54 gPrivateDnsConfiguration.clear(TEST_NETID);
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090055 // Delete cache for test
56 resolv_delete_cache_for_net(TEST_NETID);
57 }
58
Hungming Chenc6556622019-10-02 16:01:07 +080059 void SetResolverConfiguration(const std::vector<std::string>& servers = {},
60 const std::vector<std::string>& domains = {},
61 const std::vector<std::string>& tlsServers = {},
62 const std::string& tlsHostname = "",
63 const std::string& caCert = "") {
64 // Determine the DNS configuration steps from setResolverConfiguration() in
65 // packages/modules/DnsResolver/ResolverController.cpp. The gold test just needs to setup
66 // simply DNS and DNS-over-TLS server configuration. Some implementation in
67 // setResolverConfiguration() are not required. For example, limiting TLS server amount is
68 // not necessary for gold test because gold test has only one TLS server for testing
69 // so far.
70 Fwmark fwmark;
71 fwmark.netId = TEST_NETID;
72 fwmark.explicitlySelected = true;
73 fwmark.protectedFromVpn = true;
74 fwmark.permission = PERMISSION_SYSTEM;
75 ASSERT_EQ(gPrivateDnsConfiguration.set(TEST_NETID, fwmark.intValue, tlsServers, tlsHostname,
76 caCert),
77 0);
78 ASSERT_EQ(resolv_set_nameservers(TEST_NETID, servers, domains, kParams), 0);
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090079 }
80
Hungming Chenc6556622019-10-02 16:01:07 +080081 void SetResolvers() { SetResolverConfiguration(kDefaultServers, kDefaultSearchDomains); }
82
83 void SetResolversWithTls() {
84 // Pass servers as both network-assigned and TLS servers. Tests can
85 // determine on which server and by which protocol queries arrived.
86 // See also DnsClient::SetResolversWithTls() in
87 // packages/modules/DnsResolver/tests/dns_responder/dns_responder_client.h.
88 SetResolverConfiguration(kDefaultServers, kDefaultSearchDomains, kDefaultServers,
89 kDefaultPrivateDnsHostName, kCaCert);
90 }
91
92 bool WaitForPrivateDnsValidation(const std::string& serverAddr) {
93 constexpr milliseconds retryIntervalMs{20};
94 constexpr milliseconds timeoutMs{3000};
95 android::base::Timer t;
96 while (t.duration() < timeoutMs) {
97 const auto& validatedServers =
98 gPrivateDnsConfiguration.getStatus(TEST_NETID).validatedServers();
99 for (const auto& server : validatedServers) {
100 if (serverAddr == ToString(&server.ss)) return true;
101 }
102 std::this_thread::sleep_for(retryIntervalMs);
103 }
104 return false;
105 }
106
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900107 static constexpr res_params kParams = {
108 .sample_validity = 300,
109 .success_threshold = 25,
110 .min_samples = 8,
111 .max_samples = 8,
112 .base_timeout_msec = 1000,
113 .retry_count = 2,
114 };
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900115 static constexpr android_net_context kNetcontext = {
116 .app_netid = TEST_NETID,
117 .app_mark = MARK_UNSET,
118 .dns_netid = TEST_NETID,
119 .dns_mark = MARK_UNSET,
120 .uid = NET_CONTEXT_INVALID_UID,
121 };
Hungming Chenc6556622019-10-02 16:01:07 +0800122 static constexpr android_net_context kNetcontextTls = {
123 .app_netid = TEST_NETID,
124 .app_mark = MARK_UNSET,
125 .dns_netid = TEST_NETID,
126 .dns_mark = MARK_UNSET,
127 .uid = NET_CONTEXT_INVALID_UID,
128 // Set TLS flags. See also maybeFixupNetContext() in
129 // packages/modules/DnsResolver/DnsProxyListener.cpp.
130 .flags = NET_CONTEXT_FLAG_USE_DNS_OVER_TLS | NET_CONTEXT_FLAG_USE_EDNS,
131 };
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900132};
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900133class ResolvGetAddrInfo : public TestBase {};
134
Hungming Chen21c0f832019-09-20 18:38:47 +0800135// Parameterized test class definition.
136class ResolvGoldTest : public TestBase, public ::testing::WithParamInterface<std::string> {};
137
138// GetAddrInfo tests.
139INSTANTIATE_TEST_SUITE_P(GetAddrInfo, ResolvGoldTest,
140 ::testing::Values(std::string("getaddrinfo.topsite.google.pbtxt")),
141 [](const ::testing::TestParamInfo<std::string>& info) {
142 std::string name = info.param;
143 std::replace_if(
144 std::begin(name), std::end(name),
145 [](char ch) { return !std::isalnum(ch); }, '_');
146 return name;
147 });
148
149// Fixture tests.
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900150TEST_F(ResolvGetAddrInfo, RemovePacketMapping) {
151 test::DNSResponder dns(test::DNSResponder::MappingType::BINARY_PACKET);
152 ASSERT_TRUE(dns.startServer());
Hungming Chenc6556622019-10-02 16:01:07 +0800153 ASSERT_NO_FATAL_FAILURE(SetResolvers());
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900154
155 dns.addMappingBinaryPacket(kHelloExampleComQueryV4, kHelloExampleComResponseV4);
156
157 addrinfo* res = nullptr;
158 const addrinfo hints = {.ai_family = AF_INET};
159 NetworkDnsEventReported event;
160 int rv = resolv_getaddrinfo(kHelloExampleCom, nullptr, &hints, &kNetcontext, &res, &event);
161 ScopedAddrinfo result(res);
Hungming Chenc6556622019-10-02 16:01:07 +0800162 ASSERT_NE(result, nullptr);
163 ASSERT_EQ(rv, 0);
164 EXPECT_EQ(ToString(result), "1.2.3.4");
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900165
166 // Remove existing DNS record.
167 dns.removeMappingBinaryPacket(kHelloExampleComQueryV4);
168
169 // Expect to have no answer in DNS query result.
170 rv = resolv_getaddrinfo(kHelloExampleCom, nullptr, &hints, &kNetcontext, &res, &event);
171 result.reset(res);
Hungming Chenc6556622019-10-02 16:01:07 +0800172 ASSERT_EQ(result, nullptr);
173 ASSERT_EQ(rv, EAI_NODATA);
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900174}
175
176TEST_F(ResolvGetAddrInfo, ReplacePacketMapping) {
177 test::DNSResponder dns(test::DNSResponder::MappingType::BINARY_PACKET);
178 ASSERT_TRUE(dns.startServer());
Hungming Chenc6556622019-10-02 16:01:07 +0800179 ASSERT_NO_FATAL_FAILURE(SetResolvers());
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900180
181 // Register the record which uses IPv4 address 1.2.3.4.
182 dns.addMappingBinaryPacket(kHelloExampleComQueryV4, kHelloExampleComResponseV4);
183
184 // Expect that the DNS query returns IPv4 address 1.2.3.4.
185 addrinfo* res = nullptr;
186 const addrinfo hints = {.ai_family = AF_INET};
187 NetworkDnsEventReported event;
188 int rv = resolv_getaddrinfo(kHelloExampleCom, nullptr, &hints, &kNetcontext, &res, &event);
189 ScopedAddrinfo result(res);
Hungming Chenc6556622019-10-02 16:01:07 +0800190 ASSERT_NE(result, nullptr);
191 ASSERT_EQ(rv, 0);
192 EXPECT_EQ(ToString(result), "1.2.3.4");
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900193
194 // Replace the registered record with a record which uses new IPv4 address 5.6.7.8.
195 std::vector<uint8_t> newHelloExampleComResponseV4 = {
196 /* Header */
197 0x00, 0x00, /* Transaction ID: 0x0000 */
198 0x81, 0x80, /* Flags: qr rd ra */
199 0x00, 0x01, /* Questions: 1 */
200 0x00, 0x01, /* Answer RRs: 1 */
201 0x00, 0x00, /* Authority RRs: 0 */
202 0x00, 0x00, /* Additional RRs: 0 */
203 /* Queries */
204 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
205 0x03, 0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
206 0x00, 0x01, /* Type: A */
207 0x00, 0x01, /* Class: IN */
208 /* Answers */
209 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
210 0x03, 0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
211 0x00, 0x01, /* Type: A */
212 0x00, 0x01, /* Class: IN */
213 0x00, 0x00, 0x00, 0x00, /* Time to live: 0 */
214 0x00, 0x04, /* Data length: 4 */
215 0x05, 0x06, 0x07, 0x08 /* Address: 5.6.7.8 */
216 };
217 dns.addMappingBinaryPacket(kHelloExampleComQueryV4, newHelloExampleComResponseV4);
218
219 // Expect that DNS query returns new IPv4 address 5.6.7.8.
220 rv = resolv_getaddrinfo(kHelloExampleCom, nullptr, &hints, &kNetcontext, &res, &event);
221 result.reset(res);
Hungming Chenc6556622019-10-02 16:01:07 +0800222 ASSERT_NE(result, nullptr);
223 ASSERT_EQ(rv, 0);
224 EXPECT_EQ(ToString(result), "5.6.7.8");
225}
226
227TEST_F(ResolvGetAddrInfo, BasicTlsQuery) {
228 test::DNSResponder dns;
229 dns.addMapping(kHelloExampleCom, ns_type::ns_t_a, "1.2.3.4");
230 dns.addMapping(kHelloExampleCom, ns_type::ns_t_aaaa, "::1.2.3.4");
231 ASSERT_TRUE(dns.startServer());
232
233 test::DnsTlsFrontend tls;
234 ASSERT_TRUE(tls.startServer());
235 ASSERT_NO_FATAL_FAILURE(SetResolversWithTls());
236 EXPECT_TRUE(WaitForPrivateDnsValidation(tls.listen_address()));
237
238 dns.clearQueries();
239 addrinfo* res = nullptr;
240 // If the socket type is not specified, every address will appear twice, once for
241 // SOCK_STREAM and one for SOCK_DGRAM. Just pick one because the addresses for
242 // the second query of different socket type are responded by the cache.
243 const addrinfo hints = {.ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM};
244 NetworkDnsEventReported event;
245 const int rv =
246 resolv_getaddrinfo(kHelloExampleCom, nullptr, &hints, &kNetcontextTls, &res, &event);
247 ScopedAddrinfo result(res);
248 ASSERT_EQ(rv, 0);
249 EXPECT_EQ(GetNumQueries(dns, kHelloExampleCom), 2U);
250 const std::vector<std::string> result_strs = ToStrings(result);
251 EXPECT_THAT(result_strs, testing::UnorderedElementsAreArray({"1.2.3.4", "::1.2.3.4"}));
252 EXPECT_EQ(tls.queries(), 3);
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900253}
254
Hungming Chen21c0f832019-09-20 18:38:47 +0800255// Parameterized tests.
256TEST_P(ResolvGoldTest, GoldData) {
257 const auto& testFile = GetParam();
258
259 // Convert the testing configuration from .pbtxt file to proto.
260 std::string file_content;
261 ASSERT_TRUE(android::base::ReadFileToString(kTestDataPath + testFile, &file_content))
262 << strerror(errno);
263 android::net::GoldTest goldtest;
264 ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(file_content, &goldtest));
265 ASSERT_EQ(android::net::CallType::CALL_GETADDRINFO, goldtest.config().call());
266 ASSERT_TRUE(goldtest.config().has_addrinfo());
267
268 test::DNSResponder dns(test::DNSResponder::MappingType::BINARY_PACKET);
269 ASSERT_TRUE(dns.startServer());
Hungming Chenc6556622019-10-02 16:01:07 +0800270 ASSERT_NO_FATAL_FAILURE(SetResolvers());
Hungming Chen21c0f832019-09-20 18:38:47 +0800271
272 // Register packet mapping (query, response) from proto.
273 for (const auto& m : goldtest.packet_mapping()) {
274 // Convert string to bytes because .proto type "bytes" is "string" type in C++.
275 // See also the section "Scalar Value Types" in "Language Guide (proto3)".
276 dns.addMappingBinaryPacket(std::vector<uint8_t>(m.query().begin(), m.query().end()),
277 std::vector<uint8_t>(m.response().begin(), m.response().end()));
278 }
279
280 addrinfo* res = nullptr;
281 const auto& args = goldtest.config().addrinfo();
282 const addrinfo hints = {
Hungming Chen21c0f832019-09-20 18:38:47 +0800283 // Clear the flag AI_ADDRCONFIG to avoid flaky test because AI_ADDRCONFIG looks at
284 // whether connectivity is available. It makes that the resolver may send only A
285 // or AAAA DNS query per connectivity even AF_UNSPEC has been assigned. See also
286 // have_ipv6() and have_ipv4() in packages/modules/DnsResolver/getaddrinfo.cpp.
287 // TODO: Consider keeping the configuration flag AI_ADDRCONFIG once the unit
288 // test can treat the IPv4 and IPv6 connectivity.
289 .ai_flags = args.ai_flags() & ~AI_ADDRCONFIG,
Nick Desaulniersdffafb72019-11-11 16:17:57 -0800290 .ai_family = args.family(),
291 .ai_socktype = args.socktype(),
292 .ai_protocol = args.protocol(),
Hungming Chen21c0f832019-09-20 18:38:47 +0800293 };
294 NetworkDnsEventReported event;
Hungming Chenc6556622019-10-02 16:01:07 +0800295 const int rv =
296 resolv_getaddrinfo(args.host().c_str(), nullptr, &hints, &kNetcontext, &res, &event);
Hungming Chen21c0f832019-09-20 18:38:47 +0800297 ScopedAddrinfo result(res);
298 ASSERT_EQ(goldtest.result().return_code(), rv);
299
300 if (goldtest.result().return_code() != GT_EAI_NO_ERROR) {
Hungming Chenc6556622019-10-02 16:01:07 +0800301 ASSERT_EQ(result, nullptr);
Hungming Chen21c0f832019-09-20 18:38:47 +0800302 } else {
Hungming Chenc6556622019-10-02 16:01:07 +0800303 ASSERT_NE(result, nullptr);
Hungming Chen21c0f832019-09-20 18:38:47 +0800304 const auto& addresses = goldtest.result().addresses();
305 EXPECT_THAT(ToStrings(result),
306 ::testing::UnorderedElementsAreArray(
307 std::vector<std::string>(addresses.begin(), addresses.end())));
308 }
Hungming Chenc6556622019-10-02 16:01:07 +0800309 EXPECT_EQ(GetNumQueries(dns, args.host().c_str()), (hints.ai_family == AF_UNSPEC) ? 2U : 1U);
Hungming Chen21c0f832019-09-20 18:38:47 +0800310}
311
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900312} // end of namespace net
313} // end of namespace android