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