• 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 <gtest/gtest.h>
29 #include <netdutils/InternetAddresses.h>
30 
31 #include "dns_responder/dns_responder.h"
32 
33 class ScopeBlockedUIDRule {
34     using INetd = aidl::android::net::INetd;
35 
36   public:
ScopeBlockedUIDRule(INetd * netSrv,uid_t testUid)37     ScopeBlockedUIDRule(INetd* netSrv, uid_t testUid)
38         : mNetSrv(netSrv), mTestUid(testUid), mSavedUid(getuid()) {
39         // Add drop rule for testUid. Also enable the standby chain because it might not be
40         // enabled. Unfortunately we cannot use FIREWALL_CHAIN_NONE, or custom iptables rules, for
41         // this purpose because netd calls fchown() on the DNS query sockets, and "iptables -m
42         // owner" matches the UID of the socket creator, not the UID set by fchown().
43         // TODO: migrate FIREWALL_CHAIN_NONE to eBPF as well.
44         EXPECT_TRUE(mNetSrv->firewallEnableChildChain(INetd::FIREWALL_CHAIN_STANDBY, true).isOk());
45         EXPECT_TRUE(mNetSrv->firewallSetUidRule(INetd::FIREWALL_CHAIN_STANDBY, mTestUid,
46                                                 INetd::FIREWALL_RULE_DENY)
47                             .isOk());
48         EXPECT_TRUE(seteuid(mTestUid) == 0);
49     };
~ScopeBlockedUIDRule()50     ~ScopeBlockedUIDRule() {
51         // Restore uid
52         EXPECT_TRUE(seteuid(mSavedUid) == 0);
53         // Remove drop rule for testUid, and disable the standby chain.
54         EXPECT_TRUE(mNetSrv->firewallSetUidRule(INetd::FIREWALL_CHAIN_STANDBY, mTestUid,
55                                                 INetd::FIREWALL_RULE_ALLOW)
56                             .isOk());
57         EXPECT_TRUE(mNetSrv->firewallEnableChildChain(INetd::FIREWALL_CHAIN_STANDBY, false).isOk());
58     }
59 
60   private:
61     INetd* mNetSrv;
62     const uid_t mTestUid;
63     const uid_t mSavedUid;
64 };
65 
66 class ScopedChangeUID {
67   public:
ScopedChangeUID(uid_t testUid)68     ScopedChangeUID(uid_t testUid) : mTestUid(testUid), mSavedUid(getuid()) {
69         EXPECT_TRUE(seteuid(mTestUid) == 0);
70     };
~ScopedChangeUID()71     ~ScopedChangeUID() { EXPECT_TRUE(seteuid(mSavedUid) == 0); }
72 
73   private:
74     const uid_t mTestUid;
75     const uid_t mSavedUid;
76 };
77 
78 class ScopedSystemProperties {
79   public:
ScopedSystemProperties(const std::string & key,const std::string & value)80     ScopedSystemProperties(const std::string& key, const std::string& value) : mStoredKey(key) {
81         mStoredValue = android::base::GetProperty(key, "");
82         android::base::SetProperty(key, value);
83     }
~ScopedSystemProperties()84     ~ScopedSystemProperties() { android::base::SetProperty(mStoredKey, mStoredValue); }
85 
86   private:
87     std::string mStoredKey;
88     std::string mStoredValue;
89 };
90 
91 struct DnsRecord {
92     std::string host_name;  // host name
93     ns_type type;           // record type
94     std::string addr;       // ipv4/v6 address
95 };
96 
97 // TODO: make this dynamic and stop depending on implementation details.
98 constexpr int TEST_NETID = 30;
99 // Use the biggest two reserved appId for applications to avoid conflict with existing uids.
100 constexpr int TEST_UID = 99999;
101 constexpr int TEST_UID2 = 99998;
102 
103 static constexpr char kLocalHost[] = "localhost";
104 static constexpr char kLocalHostAddr[] = "127.0.0.1";
105 static constexpr char kIp6LocalHost[] = "ip6-localhost";
106 static constexpr char kIp6LocalHostAddr[] = "::1";
107 static constexpr char kHelloExampleCom[] = "hello.example.com.";
108 static constexpr char kHelloExampleComAddrV4[] = "1.2.3.4";
109 static constexpr char kHelloExampleComAddrV6[] = "::1.2.3.4";
110 static constexpr char kExampleComDomain[] = ".example.com";
111 
112 static const std::string kNat64Prefix = "64:ff9b::/96";
113 static const std::string kNat64Prefix2 = "2001:db8:6464::/96";
114 
115 constexpr size_t kMaxmiumLabelSize = 63;  // see RFC 1035 section 2.3.4.
116 
117 static const std::vector<uint8_t> kHelloExampleComQueryV4 = {
118         /* Header */
119         0x00, 0x00, /* Transaction ID: 0x0000 */
120         0x01, 0x00, /* Flags: rd */
121         0x00, 0x01, /* Questions: 1 */
122         0x00, 0x00, /* Answer RRs: 0 */
123         0x00, 0x00, /* Authority RRs: 0 */
124         0x00, 0x00, /* Additional RRs: 0 */
125         /* Queries */
126         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
127         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
128         0x00, 0x01,             /* Type: A */
129         0x00, 0x01              /* Class: IN */
130 };
131 
132 static const std::vector<uint8_t> kHelloExampleComResponseV4 = {
133         /* Header */
134         0x00, 0x00, /* Transaction ID: 0x0000 */
135         0x81, 0x80, /* Flags: qr rd ra */
136         0x00, 0x01, /* Questions: 1 */
137         0x00, 0x01, /* Answer RRs: 1 */
138         0x00, 0x00, /* Authority RRs: 0 */
139         0x00, 0x00, /* Additional RRs: 0 */
140         /* Queries */
141         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
142         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
143         0x00, 0x01,             /* Type: A */
144         0x00, 0x01,             /* Class: IN */
145         /* Answers */
146         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
147         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
148         0x00, 0x01,             /* Type: A */
149         0x00, 0x01,             /* Class: IN */
150         0x00, 0x00, 0x00, 0x00, /* Time to live: 0 */
151         0x00, 0x04,             /* Data length: 4 */
152         0x01, 0x02, 0x03, 0x04  /* Address: 1.2.3.4 */
153 };
154 
155 // Illegal hostnames
156 static constexpr char kBadCharAfterPeriodHost[] = "hello.example.^com.";
157 static constexpr char kBadCharBeforePeriodHost[] = "hello.example^.com.";
158 static constexpr char kBadCharAtTheEndHost[] = "hello.example.com^.";
159 static constexpr char kBadCharInTheMiddleOfLabelHost[] = "hello.ex^ample.com.";
160 
161 static const test::DNSHeader kDefaultDnsHeader = {
162         // Don't need to initialize the flag "id" and "rd" because DNS responder assigns them from
163         // query to response. See RFC 1035 section 4.1.1.
164         .id = 0,                // unused. should be assigned from query to response
165         .ra = false,            // recursive query support is not available
166         .rcode = ns_r_noerror,  // no error
167         .qr = true,             // message is a response
168         .opcode = QUERY,        // a standard query
169         .aa = false,            // answer/authority portion was not authenticated by the server
170         .tr = false,            // message is not truncated
171         .rd = false,            // unused. should be assigned from query to response
172         .ad = false,            // non-authenticated data is unacceptable
173 };
174 
175 // The CNAME chain records for building a response message which exceeds 512 bytes.
176 //
177 // Ignoring the other fields of the message, the response message has 8 CNAMEs in 5 answer RRs
178 // and each CNAME has 77 bytes as the follows. The response message at least has 616 bytes in
179 // answer section and has already exceeded 512 bytes totally.
180 //
181 // The CNAME is presented as:
182 //   0   1            64  65                          72  73          76  77
183 //   +---+--........--+---+---+---+---+---+---+---+---+---+---+---+---+---+
184 //   | 63| {x, .., x} | 7 | e | x | a | m | p | l | e | 3 | c | o | m | 0 |
185 //   +---+--........--+---+---+---+---+---+---+---+---+---+---+---+---+---+
186 //          ^-- x = {a, b, c, d}
187 //
188 const std::string kCnameA = std::string(kMaxmiumLabelSize, 'a') + kExampleComDomain + ".";
189 const std::string kCnameB = std::string(kMaxmiumLabelSize, 'b') + kExampleComDomain + ".";
190 const std::string kCnameC = std::string(kMaxmiumLabelSize, 'c') + kExampleComDomain + ".";
191 const std::string kCnameD = std::string(kMaxmiumLabelSize, 'd') + kExampleComDomain + ".";
192 const std::vector<DnsRecord> kLargeCnameChainRecords = {
193         {kHelloExampleCom, ns_type::ns_t_cname, kCnameA},
194         {kCnameA, ns_type::ns_t_cname, kCnameB},
195         {kCnameB, ns_type::ns_t_cname, kCnameC},
196         {kCnameC, ns_type::ns_t_cname, kCnameD},
197         {kCnameD, ns_type::ns_t_a, kHelloExampleComAddrV4},
198 };
199 
200 // TODO: Integrate GetNumQueries relevent functions
201 size_t GetNumQueries(const test::DNSResponder& dns, const char* name);
202 size_t GetNumQueriesForProtocol(const test::DNSResponder& dns, const int protocol,
203                                 const char* name);
204 size_t GetNumQueriesForType(const test::DNSResponder& dns, ns_type type, const char* name);
205 std::string ToString(const hostent* he);
206 std::string ToString(const addrinfo* ai);
207 std::string ToString(const android::netdutils::ScopedAddrinfo& ai);
208 std::string ToString(const sockaddr_storage* addr);
209 std::vector<std::string> ToStrings(const hostent* he);
210 std::vector<std::string> ToStrings(const addrinfo* ai);
211 std::vector<std::string> ToStrings(const android::netdutils::ScopedAddrinfo& ai);
212 
213 // Wait for |condition| to be met until |timeout|.
214 bool PollForCondition(const std::function<bool()>& condition,
215                       std::chrono::milliseconds timeout = std::chrono::milliseconds(1000));
216 
217 android::netdutils::ScopedAddrinfo safe_getaddrinfo(const char* node, const char* service,
218                                                     const struct addrinfo* hints);
219 
220 void SetMdnsRoute();
221 void RemoveMdnsRoute();