• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 #pragma once
19 
20 #include <arpa/nameser.h>
21 #include <netdb.h>
22 
23 #include <string>
24 #include <vector>
25 
26 #include <aidl/android/net/INetd.h>
27 #include <android-base/properties.h>
28 #include <android-modules-utils/sdk_level.h>
29 #include <firewall.h>
30 #include <gtest/gtest.h>
31 #include <netdutils/InternetAddresses.h>
32 
33 #include "dns_responder/dns_responder.h"
34 
35 class ScopeBlockedUIDRule {
36     using INetd = aidl::android::net::INetd;
37 
38   public:
ScopeBlockedUIDRule(INetd * netSrv,uid_t testUid)39     ScopeBlockedUIDRule(INetd* netSrv, uid_t testUid)
40         : mNetSrv(netSrv), mTestUid(testUid), mSavedUid(getuid()) {
41         // Add drop rule for testUid. Also enable the standby chain because it might not be
42         // enabled. Unfortunately we cannot use FIREWALL_CHAIN_NONE, or custom iptables rules, for
43         // this purpose because netd calls fchown() on the DNS query sockets, and "iptables -m
44         // owner" matches the UID of the socket creator, not the UID set by fchown().
45         // TODO: migrate FIREWALL_CHAIN_NONE to eBPF as well.
46         if (android::modules::sdklevel::IsAtLeastT()) {
47             mFw = Firewall::getInstance();
48             EXPECT_RESULT_OK(mFw->toggleStandbyMatch(true));
49             EXPECT_RESULT_OK(mFw->addRule(mTestUid, STANDBY_MATCH));
50         } else {
51             EXPECT_TRUE(
52                     mNetSrv->firewallEnableChildChain(INetd::FIREWALL_CHAIN_STANDBY, true).isOk());
53             EXPECT_TRUE(mNetSrv->firewallSetUidRule(INetd::FIREWALL_CHAIN_STANDBY, mTestUid,
54                                                     INetd::FIREWALL_RULE_DENY)
55                                 .isOk());
56         }
57         EXPECT_TRUE(seteuid(mTestUid) == 0);
58     };
~ScopeBlockedUIDRule()59     ~ScopeBlockedUIDRule() {
60         // Restore uid
61         EXPECT_TRUE(seteuid(mSavedUid) == 0);
62         // Remove drop rule for testUid, and disable the standby chain.
63         if (android::modules::sdklevel::IsAtLeastT()) {
64             EXPECT_RESULT_OK(mFw->removeRule(mTestUid, STANDBY_MATCH));
65             EXPECT_RESULT_OK(mFw->toggleStandbyMatch(false));
66         } else {
67             EXPECT_TRUE(mNetSrv->firewallSetUidRule(INetd::FIREWALL_CHAIN_STANDBY, mTestUid,
68                                                     INetd::FIREWALL_RULE_ALLOW)
69                                 .isOk());
70             EXPECT_TRUE(
71                     mNetSrv->firewallEnableChildChain(INetd::FIREWALL_CHAIN_STANDBY, false).isOk());
72         }
73     }
74 
75   private:
76     INetd* mNetSrv;
77     Firewall* mFw;
78     const uid_t mTestUid;
79     const uid_t mSavedUid;
80 };
81 
82 class ScopedChangeUID {
83   public:
ScopedChangeUID(uid_t testUid)84     ScopedChangeUID(uid_t testUid) : mTestUid(testUid), mSavedUid(getuid()) {
85         EXPECT_TRUE(seteuid(mTestUid) == 0);
86     };
~ScopedChangeUID()87     ~ScopedChangeUID() { EXPECT_TRUE(seteuid(mSavedUid) == 0); }
88 
89   private:
90     const uid_t mTestUid;
91     const uid_t mSavedUid;
92 };
93 
94 class ScopedSystemProperties {
95   public:
ScopedSystemProperties(const std::string & key,const std::string & value)96     ScopedSystemProperties(const std::string& key, const std::string& value) : mStoredKey(key) {
97         mStoredValue = android::base::GetProperty(key, "");
98         android::base::SetProperty(key, value);
99     }
~ScopedSystemProperties()100     ~ScopedSystemProperties() { android::base::SetProperty(mStoredKey, mStoredValue); }
101 
102   private:
103     std::string mStoredKey;
104     std::string mStoredValue;
105 };
106 
107 class ScopedDefaultNetwork {
108     using INetd = aidl::android::net::INetd;
109 
110   public:
ScopedDefaultNetwork(INetd * netSrv,uid_t testDefaultNetwork)111     ScopedDefaultNetwork(INetd* netSrv, uid_t testDefaultNetwork) : mNetSrv(netSrv) {
112         EXPECT_TRUE(mNetSrv->networkGetDefault(&mStoredDefaultNetwork).isOk());
113         EXPECT_TRUE(mNetSrv->networkSetDefault(testDefaultNetwork).isOk());
114     };
~ScopedDefaultNetwork()115     ~ScopedDefaultNetwork() {
116         EXPECT_TRUE(mNetSrv->networkSetDefault(mStoredDefaultNetwork).isOk());
117     }
118 
119   private:
120     INetd* mNetSrv;
121     int mStoredDefaultNetwork;
122 };
123 
124 struct DnsRecord {
125     std::string host_name;  // host name
126     ns_type type;           // record type
127     std::string addr;       // ipv4/v6 address
128 };
129 
130 // TODO: make this dynamic and stop depending on implementation details.
131 constexpr int TEST_NETID = 30;
132 // Use the biggest two reserved appId for applications to avoid conflict with existing uids.
133 constexpr int TEST_UID = 99999;
134 constexpr int TEST_UID2 = 99998;
135 
136 constexpr char kDnsPortString[] = "53";
137 constexpr char kDohPortString[] = "443";
138 constexpr char kDotPortString[] = "853";
139 
140 const std::string kFlagPrefix("persist.device_config.netd_native.");
141 
142 const std::string kDohEarlyDataFlag(kFlagPrefix + "doh_early_data");
143 const std::string kDohFlag(kFlagPrefix + "doh");
144 const std::string kDohIdleTimeoutFlag(kFlagPrefix + "doh_idle_timeout_ms");
145 const std::string kDohProbeTimeoutFlag(kFlagPrefix + "doh_probe_timeout_ms");
146 const std::string kDohQueryTimeoutFlag(kFlagPrefix + "doh_query_timeout_ms");
147 const std::string kDohSessionResumptionFlag(kFlagPrefix + "doh_session_resumption");
148 const std::string kDotAsyncHandshakeFlag(kFlagPrefix + "dot_async_handshake");
149 const std::string kDotConnectTimeoutMsFlag(kFlagPrefix + "dot_connect_timeout_ms");
150 const std::string kDotMaxretriesFlag(kFlagPrefix + "dot_maxtries");
151 const std::string kDotQueryTimeoutMsFlag(kFlagPrefix + "dot_query_timeout_ms");
152 const std::string kDotQuickFallbackFlag(kFlagPrefix + "dot_quick_fallback");
153 const std::string kDotRevalidationThresholdFlag(kFlagPrefix + "dot_revalidation_threshold");
154 const std::string kDotXportUnusableThresholdFlag(kFlagPrefix + "dot_xport_unusable_threshold");
155 const std::string kDotValidationLatencyFactorFlag(kFlagPrefix + "dot_validation_latency_factor");
156 const std::string kDotValidationLatencyOffsetMsFlag(kFlagPrefix +
157                                                     "dot_validation_latency_offset_ms");
158 const std::string kKeepListeningUdpFlag(kFlagPrefix + "keep_listening_udp");
159 const std::string kParallelLookupSleepTimeFlag(kFlagPrefix + "parallel_lookup_sleep_time");
160 const std::string kRetransIntervalFlag(kFlagPrefix + "retransmission_time_interval");
161 const std::string kRetryCountFlag(kFlagPrefix + "retry_count");
162 const std::string kSkip4aQueryOnV6LinklocalAddrFlag(kFlagPrefix +
163                                                     "skip_4a_query_on_v6_linklocal_addr");
164 const std::string kSortNameserversFlag(kFlagPrefix + "sort_nameservers");
165 
166 static constexpr char kLocalHost[] = "localhost";
167 static constexpr char kLocalHostAddr[] = "127.0.0.1";
168 static constexpr char kIp6LocalHost[] = "ip6-localhost";
169 static constexpr char kIp6LocalHostAddr[] = "::1";
170 static constexpr char kHelloExampleCom[] = "hello.example.com.";
171 static constexpr char kHelloExampleComAddrV4[] = "1.2.3.4";
172 static constexpr char kHelloExampleComAddrV4_2[] = "8.8.8.8";
173 static constexpr char kHelloExampleComAddrV4_3[] = "81.117.21.202";
174 static constexpr char kHelloExampleComAddrV6[] = "::1.2.3.4";
175 static constexpr char kHelloExampleComAddrV6_IPV4COMPAT[] = "::1.2.3.4";
176 static constexpr char kHelloExampleComAddrV6_TEREDO[] = "2001::47c1";
177 static constexpr char kHelloExampleComAddrV6_GUA[] = "2404:6800::5175:15ca";
178 static constexpr char kExampleComDomain[] = ".example.com";
179 
180 static const std::string kNat64Prefix = "64:ff9b::/96";
181 static const std::string kNat64Prefix2 = "2001:db8:6464::/96";
182 
183 constexpr size_t kMaxmiumLabelSize = 63;  // see RFC 1035 section 2.3.4.
184 
185 static const std::vector<uint8_t> kHelloExampleComQueryV4 = {
186         /* Header */
187         0x00, 0x00, /* Transaction ID: 0x0000 */
188         0x01, 0x00, /* Flags: rd */
189         0x00, 0x01, /* Questions: 1 */
190         0x00, 0x00, /* Answer RRs: 0 */
191         0x00, 0x00, /* Authority RRs: 0 */
192         0x00, 0x00, /* Additional RRs: 0 */
193         /* Queries */
194         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
195         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
196         0x00, 0x01,             /* Type: A */
197         0x00, 0x01              /* Class: IN */
198 };
199 
200 static const std::vector<uint8_t> kHelloExampleComResponseV4 = {
201         /* Header */
202         0x00, 0x00, /* Transaction ID: 0x0000 */
203         0x81, 0x80, /* Flags: qr rd ra */
204         0x00, 0x01, /* Questions: 1 */
205         0x00, 0x01, /* Answer RRs: 1 */
206         0x00, 0x00, /* Authority RRs: 0 */
207         0x00, 0x00, /* Additional RRs: 0 */
208         /* Queries */
209         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
210         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
211         0x00, 0x01,             /* Type: A */
212         0x00, 0x01,             /* Class: IN */
213         /* Answers */
214         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
215         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
216         0x00, 0x01,             /* Type: A */
217         0x00, 0x01,             /* Class: IN */
218         0x00, 0x00, 0x00, 0x00, /* Time to live: 0 */
219         0x00, 0x04,             /* Data length: 4 */
220         0x01, 0x02, 0x03, 0x04  /* Address: 1.2.3.4 */
221 };
222 
223 const std::vector<uint8_t> kHelloExampleComResponsesV4 = {
224         // scapy.DNS(
225         //   id=0,
226         //   qr=1,
227         //   ra=1,
228         //   qd=scapy.DNSQR(qname="hello.example.com",qtype="A"),
229         //   an=scapy.DNSRR(rrname="hello.example.com",type="A",ttl=0,rdata='1.2.3.4') /
230         //      scapy.DNSRR(rrname="hello.example.com",type="A",ttl=0,rdata='8.8.8.8') /
231         //      scapy.DNSRR(rrname="hello.example.com",type="A",ttl=0,rdata='81.117.21.202'))
232         /* Header */
233         0x00, 0x00, /* Transaction ID: 0x0000 */
234         0x81, 0x80, /* Flags: qr rd ra */
235         0x00, 0x01, /* Questions: 1 */
236         0x00, 0x03, /* Answer RRs: 3 */
237         0x00, 0x00, /* Authority RRs: 0 */
238         0x00, 0x00, /* Additional RRs: 0 */
239         /* Queries */
240         0x05, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x03,
241         0x63, 0x6F, 0x6D, 0x00, /* Name: hello.example.com */
242         0x00, 0x01,             /* Type: A */
243         0x00, 0x01,             /* Class: IN */
244         /* Answers */
245         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
246         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
247         0x00, 0x01,             /* Type: A */
248         0x00, 0x01,             /* Class: IN */
249         0x00, 0x00, 0x00, 0x00, /* Time to live: 0 */
250         0x00, 0x04,             /* Data length: 4 */
251         0x01, 0x02, 0x03, 0x04, /* Address: 1.2.3.4 */
252         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
253         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
254         0x00, 0x01,             /* Type: A */
255         0x00, 0x01,             /* Class: IN */
256         0x00, 0x00, 0x00, 0x00, /* Time to live: 0 */
257         0x00, 0x04,             /* Data length: 4 */
258         0x08, 0x08, 0x08, 0x08, /* Address: 8.8.8.8 */
259         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
260         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
261         0x00, 0x01,             /* Type: A */
262         0x00, 0x01,             /* Class: IN */
263         0x00, 0x00, 0x00, 0x00, /* Time to live: 0 */
264         0x00, 0x04,             /* Data length: 4 */
265         0x51, 0x75, 0x15, 0xca  /* Address: 81.117.21.202 */
266 };
267 
268 static const std::vector<uint8_t> kHelloExampleComQueryV6 = {
269         /* Header */
270         0x00, 0x00, /* Transaction ID: 0x0000 */
271         0x01, 0x00, /* Flags: rd */
272         0x00, 0x01, /* Questions: 1 */
273         0x00, 0x00, /* Answer RRs: 0 */
274         0x00, 0x00, /* Authority RRs: 0 */
275         0x00, 0x00, /* Additional RRs: 0 */
276         /* Queries */
277         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
278         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
279         0x00, 0x1c,             /* Type: AAAA */
280         0x00, 0x01              /* Class: IN */
281 };
282 
283 const std::vector<uint8_t> kHelloExampleComResponsesV6 = {
284         // The addresses are IPv4-compatible address, teredo tunneling address and global unicast
285         // address.
286         //
287         // scapy.DNS(
288         // id=0,
289         // qr=1,
290         // ra=1,
291         // qd=scapy.DNSQR(qname="hello.example.com",qtype="AAAA"),
292         // an=scapy.DNSRR(rrname="hello.example.com",type="AAAA",rdata='::1.2.3.4') /
293         //    scapy.DNSRR(rrname="hello.example.com",type="AAAA",rdata='2001::47c1') /
294         //    scapy.DNSRR(rrname="hello.example.com",type="AAAA",rdata='2404:6800::5175:15ca'))
295         /* Header */
296         0x00, 0x00, /* Transaction ID: 0x0000 */
297         0x81, 0x80, /* Flags: qr rd ra */
298         0x00, 0x01, /* Questions: 1 */
299         0x00, 0x03, /* Answer RRs: 3 */
300         0x00, 0x00, /* Authority RRs: 0 */
301         0x00, 0x00, /* Additional RRs: 0 */
302         /* Queries */
303         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
304         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
305         0x00, 0x1c,             /* Type: AAAA */
306         0x00, 0x01,             /* Class: IN */
307         /* Answers */
308         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
309         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
310         0x00, 0x1c,             /* Type: AAAA */
311         0x00, 0x01,             /* Class: IN */
312         0x00, 0x00, 0x00, 0x00, /* Time to live: 0 */
313         0x00, 0x10,             /* Data length: 4 */
314         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
315         0x04, /* Address: ::1.2.3.4 */
316         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
317         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
318         0x00, 0x1c,             /* Type: AAAA */
319         0x00, 0x01,             /* Class: IN */
320         0x00, 0x00, 0x00, 0x00, /* Time to live: 0 */
321         0x00, 0x10,             /* Data length: 4 */
322         0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
323         0xc1, /* Address: 2001::47c1 */
324         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
325         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
326         0x00, 0x1c,             /* Type: AAAA */
327         0x00, 0x01,             /* Class: IN */
328         0x00, 0x00, 0x00, 0x00, /* Time to live: 0 */
329         0x00, 0x10,             /* Data length: 4 */
330         0x24, 0x04, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x75, 0x15,
331         0xCA /* Address: 2404:6800::5175:15ca */
332 };
333 
334 // Illegal hostnames
335 static constexpr char kBadCharAfterPeriodHost[] = "hello.example.^com.";
336 static constexpr char kBadCharBeforePeriodHost[] = "hello.example^.com.";
337 static constexpr char kBadCharAtTheEndHost[] = "hello.example.com^.";
338 static constexpr char kBadCharInTheMiddleOfLabelHost[] = "hello.ex^ample.com.";
339 
340 static const test::DNSHeader kDefaultDnsHeader = {
341         // Don't need to initialize the flag "id" and "rd" because DNS responder assigns them from
342         // query to response. See RFC 1035 section 4.1.1.
343         .id = 0,                // unused. should be assigned from query to response
344         .ra = false,            // recursive query support is not available
345         .rcode = ns_r_noerror,  // no error
346         .qr = true,             // message is a response
347         .opcode = QUERY,        // a standard query
348         .aa = false,            // answer/authority portion was not authenticated by the server
349         .tr = false,            // message is not truncated
350         .rd = false,            // unused. should be assigned from query to response
351         .ad = false,            // non-authenticated data is unacceptable
352 };
353 
354 // The CNAME chain records for building a response message which exceeds 512 bytes.
355 //
356 // Ignoring the other fields of the message, the response message has 8 CNAMEs in 5 answer RRs
357 // and each CNAME has 77 bytes as the follows. The response message at least has 616 bytes in
358 // answer section and has already exceeded 512 bytes totally.
359 //
360 // The CNAME is presented as:
361 //   0   1            64  65                          72  73          76  77
362 //   +---+--........--+---+---+---+---+---+---+---+---+---+---+---+---+---+
363 //   | 63| {x, .., x} | 7 | e | x | a | m | p | l | e | 3 | c | o | m | 0 |
364 //   +---+--........--+---+---+---+---+---+---+---+---+---+---+---+---+---+
365 //          ^-- x = {a, b, c, d}
366 //
367 const std::string kCnameA = std::string(kMaxmiumLabelSize, 'a') + kExampleComDomain + ".";
368 const std::string kCnameB = std::string(kMaxmiumLabelSize, 'b') + kExampleComDomain + ".";
369 const std::string kCnameC = std::string(kMaxmiumLabelSize, 'c') + kExampleComDomain + ".";
370 const std::string kCnameD = std::string(kMaxmiumLabelSize, 'd') + kExampleComDomain + ".";
371 const std::vector<DnsRecord> kLargeCnameChainRecords = {
372         {kHelloExampleCom, ns_type::ns_t_cname, kCnameA},
373         {kCnameA, ns_type::ns_t_cname, kCnameB},
374         {kCnameB, ns_type::ns_t_cname, kCnameC},
375         {kCnameC, ns_type::ns_t_cname, kCnameD},
376         {kCnameD, ns_type::ns_t_a, kHelloExampleComAddrV4},
377 };
378 
379 // TODO: Integrate GetNumQueries relevent functions
380 size_t GetNumQueries(const test::DNSResponder& dns, const char* name);
381 size_t GetNumQueriesForProtocol(const test::DNSResponder& dns, const int protocol,
382                                 const char* name);
383 size_t GetNumQueriesForType(const test::DNSResponder& dns, ns_type type, const char* name);
384 std::string ToString(const hostent* he);
385 std::string ToString(const addrinfo* ai);
386 std::string ToString(const android::netdutils::ScopedAddrinfo& ai);
387 std::string ToString(const sockaddr_storage* addr);
388 std::vector<std::string> ToStrings(const hostent* he);
389 std::vector<std::string> ToStrings(const addrinfo* ai);
390 std::vector<std::string> ToStrings(const android::netdutils::ScopedAddrinfo& ai);
391 
392 // Wait for |condition| to be met until |timeout|.
393 bool PollForCondition(const std::function<bool()>& condition,
394                       std::chrono::milliseconds timeout = std::chrono::milliseconds(1000));
395 
396 android::netdutils::ScopedAddrinfo safe_getaddrinfo(const char* node, const char* service,
397                                                     const struct addrinfo* hints);
398 
399 void SetMdnsRoute();
400 void RemoveMdnsRoute();
401